IdentifiableType and Equatable, and your section with AnimatableSectionModelTypeInsert, Reload and Delete (Automatic, Fade, ...)UITableView and UICollectionViewWriting table and collection view data sources is tedious. There is a large number of delegate methods that need to be implemented for the simplest case possible.
RxSwift helps alleviate some of the burden with a simple data binding mechanism:
1) Turn your data into an Observable sequence
2) Bind the data to the tableView/collectionView using one of:
- rx.items(dataSource:protocol<RxTableViewDataSourceType, UITableViewDataSource>)
- rx.items(cellIdentifier:String)
- rx.items(cellIdentifier:String:Cell.Type:_:)
- rx.items(_:_:)
let data = Observable<[String]>.just(["first element", "second element", "third element"])
data.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { index, model, cell in
cell.textLabel?.text = model
}
.disposed(by: disposeBag)
This works well with simple data sets but does not handle cases where you need to bind complex data sets with multiples sections, or when you need to perform animations when adding/modifying/deleting items.
These are precisely the use cases that RxDataSources helps solve.
With RxDataSources, it is super easy to just write
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Int>>(configureCell: configureCell)
Observable.just([SectionModel(model: "title", items: [1, 2, 3])])
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)

Given the following custom data structure:swift struct CustomData { var anInt: Int var aString: String var aCGPoint: CGPoint }
1) Start by defining your sections with a struct that conforms to the SectionModelType protocol:
- define the Item typealias: equal to the type of items that the section will contain
- declare an items property: of type array of Item
struct SectionOfCustomData {
var header: String
var items: [Item]
}
extension SectionOfCustomData: SectionModelType {
typealias Item = CustomData
init(original: SectionOfCustomData, items: [Item]) {
self = original
self.items = items
}
}
2) Create a dataSource object and pass it your SectionOfCustomData type:swift let dataSource = RxTableViewSectionedReloadDataSource<SectionOfCustomData>( configureCell: { dataSource, tableView, indexPath, item in let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = "Item \(item.anInt): \(item.aString) - \(item.aCGPoint.x):\(item.aCGPoint.y)" return cell })
3) Customize closures on the dataSource as needed:
- titleForHeaderInSection
- titleForFooterInSection
- etc
dataSource.titleForHeaderInSection = { dataSource, index in
return dataSource.sectionModels[index].header
}
dataSource.titleForFooterInSection = { dataSource, index in
return dataSource.sectionModels[index].footer
}
dataSource.canEditRowAtIndexPath = { dataSource, indexPath in
return true
}
dataSource.canMoveRowAtIndexPath = { dataSource, indexPath in
return true
}
4) Define the actual data as an Observable sequence of CustomData objects and bind it to the tableView
```swift
let sections = [
SectionOfCustomData(header: "First section", items: [CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero), CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1)) ]),
SectionOfCustomData(header: "Second section", items: [CustomData(anInt: 2, aString: "two", aCGPoint: CGPoint(x: 2, y: 2)), CustomData(anInt: 3, aString: "three", aCGPoint: CGPoint(x: 3, y: 3)) ])
]
Observable.just(sections)
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
```
RxDataSources provides two special data source types that automatically take care of animating changes in the bound data source: RxTableViewSectionedAnimatedDataSource and RxCollectionViewSectionedAnimatedDataSource.
To use one of the two animated data sources, you must take a few extra steps on top of those outlined above:
AnimatableSectionModelTypeIdentifiableType: The identity provided by the IdentifiableType protocol must be an immutable identifier representing an instance of the model. For example, in case of a Car model, you might want to use the car's plateNumber as its identity.Equatable: Conforming to Equatable helps RxDataSources determine which cells have changed so it can animate only these specific cells. Meaning, changing any of the Car model's properties will trigger an animated reload of that cell.Xcode 10.2
Swift 5.0
For Swift 4.x version please use versions 3.0.0 ... 3.1.0
For Swift 3.x version please use versions 1.0 ... 2.0.2
For Swift 2.3 version please use versions 0.1 ... 0.9
We'll try to keep the API as stable as possible, but breaking API changes can occur.
Podfile pod 'RxDataSources', '~> 4.0'
Cartfile github "RxSwiftCommunity/RxDataSources" ~> 4.0
Create a Package.swift file.
import PackageDescription
let package = Package(
name: "SampleProject",
dependencies: [
.package(url: "https://github.com/RxSwiftCommunity/RxDataSources.git", from: "4.0.0")
]
)
If you are using Xcode 11 or higher, go to File / Swift Packages / Add Package Dependency... and enter package repository URL **https://github.com/RxSwiftCommunity/RxDataSources.git**, then follow the instructions.