Created
August 31, 2018 13:34
-
-
Save loromits/3f74a105131a7bba76eb73ade162ac10 to your computer and use it in GitHub Desktop.
Rx dataSource with Diff's update command exposed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Differentiator | |
import RxCocoa | |
import RxDataSources | |
import RxSwift | |
import UIKit | |
class RxTableViewSectionedUpdatingDataSource<S: AnimatableSectionModelType>: | |
TableViewSectionedDataSource<S>, RxTableViewDataSourceType { | |
typealias UpdateCell = (UITableViewCell, IndexPath, S.Item) -> Void | |
private let animationConfiguration: AnimationConfiguration | |
private let updateCell: UpdateCell | |
init(animationConfiguration: AnimationConfiguration = AnimationConfiguration(), | |
getCell: @escaping (UITableView, IndexPath, S.Item) -> UITableViewCell, | |
updateCell: @escaping UpdateCell) { | |
self.animationConfiguration = animationConfiguration | |
self.updateCell = updateCell | |
super.init(configureCell: { _, tableView, indexPath, item in | |
let cell = getCell(tableView, indexPath, item) | |
updateCell(cell, indexPath, item) | |
return cell | |
}) | |
} | |
private var dataSet = false | |
public func tableView(_ tableView: UITableView, observedEvent: Event<[S]>) { | |
Binder(self) { dataSource, newSections in | |
guard dataSource.dataSet else { | |
dataSource.dataSet = true | |
dataSource.setSections(newSections) | |
return tableView.reloadData() | |
} | |
guard tableView.window != nil, //tableView isn't in view hierarchy | |
let differences = try? Diff.differencesForSectionedView(initialSections: dataSource.sectionModels, | |
finalSections: newSections) | |
else { | |
dataSource.setSections(newSections) | |
return tableView.reloadData() | |
} | |
for difference in differences { | |
dataSource.setSections(difference.finalSections) | |
dataSource.performBatchUpdates(difference, forTable: tableView) | |
} | |
} | |
.on(observedEvent) | |
} | |
private func performBatchUpdates(_ updates: Changeset<S>, forTable tableView: UITableView) { | |
tableView.beginUpdates() | |
tableView.deleteSections(updates.deletedSections, | |
animationStyle: animationConfiguration.deleteAnimation) | |
tableView.insertSections(updates.insertedSections, | |
animationStyle: animationConfiguration.insertAnimation) | |
for (from, to) in updates.movedSections { | |
tableView.moveSection(from, to: to) | |
} | |
tableView.deleteItemsAtIndexPaths( | |
updates.deletedItems.map { IndexPath(item: $0.itemIndex, section: $0.sectionIndex) }, | |
animationStyle: animationConfiguration.deleteAnimation | |
) | |
tableView.insertItemsAtIndexPaths( | |
updates.insertedItems.map { IndexPath(item: $0.itemIndex, section: $0.sectionIndex) }, | |
animationStyle: animationConfiguration.insertAnimation | |
) | |
for (from, to) in updates.movedItems { | |
tableView.moveItemAtIndexPath(IndexPath(item: from.itemIndex, section: from.sectionIndex), | |
to: IndexPath(item: to.itemIndex, section: to.sectionIndex)) | |
} | |
tableView.endUpdates() | |
updates.updatedItems | |
.map { IndexPath(item: $0.itemIndex, section: $0.sectionIndex) } | |
.forEach { indexPath in | |
if let cell = tableView.cellForRow(at: indexPath) { | |
updateCell(cell, indexPath, self[indexPath]) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment