Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save loromits/3f74a105131a7bba76eb73ade162ac10 to your computer and use it in GitHub Desktop.
Save loromits/3f74a105131a7bba76eb73ade162ac10 to your computer and use it in GitHub Desktop.
Rx dataSource with Diff's update command exposed
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