RxSwiftCommunity / RxDataSources使用介绍
翻译自https://github.com/RxSwiftCommunity/RxDataSources
Table and Collection view data sources
特点
- O(N)的算法计算差异
- 这个算法假设所有的sections和items是唯一的,因此没有二义性
- 在有二义性的情况下,没有动画刷新时自动回退
- 它使用附加的启发式来传送最少的命令给sections view
- 尽管运行时间是线性的,但实际发送的命令数远少于线性
- 最好(也可能)将更改的数量限制为一个小的数字,如果更改的数量朝着线性增长,只需进行正常的重新加载
- 支持对你的item和section进行扩展
- 仅仅扩展具有
IdentifiableType
和Equatable
的item,和具有AnimatableSectionModelType
的section
- 仅仅扩展具有
-
支持item和section的两级分层动画的所有组合
- section层动画:Insert,Delete,Move
- item层动画:Insert,Delete,Move,Reload(如果值发生改变)
- 可配置的Insert、Reload和Delete(像自动、淡入淡出)
- 样例app
- 随机压力测试(样例app)
- 支持开箱即用的编辑(样例app)
- 可以在 UITableView 和 UICollectionView 中使用
为什么
编写table和collection view 的data source 是非常麻烦的,即使是最简单的情况,也需要大量的代理.
RxSwift通过简单的数据绑定机制来减轻负担.
- 把你的数据转换成Observable序列
- 使用如下之一将数据绑定到TableView和CollectionView:
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)
这对简单的数据集很有效,但是它没有处理将复杂的数据绑定到多个sections上的情况,或者当你需要给 adding/modifying/deleting items 增加动画时.
这正是RxDataSource帮忙解决的情况.
有RxDataSource,只需要这样:
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)
如何用
给定如下的结构体
struct CustomData {
var anInt: Int
var aString: String
var aCGPoint: CGPoint
}
1. Start. 将你的sections定义为一个结构体,它遵循 SectionModelType
协议
- 定义 Item typealias :等于Section将包含的item的类型
- 定义一个 Items 属性: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. 创建一个dataSource对象,将你定义的SectionOfCustomData类型传给它
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. 根据需要自定义DataSource上的闭包
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. 将实际的数据转换为CustomDatal obeject类型的Observable sequence,并绑定到tableview上
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提供了两种特殊的数据源类型,可以自动处理绑定在数据源中的动画更改:RxTableViewSectionedAnimatedDataSource
和 RxCollectionViewSectionedAnimatedDataSource
.
要使用这两种数据源,要在上面步骤的基础上增加一些额外的步骤:
SectionOfCustomData
需要符合
AnimatableSectionModelType
协议- 你的数据必须满足:
IdentifiableType
:必须给IdentifiableType
提供一个属于某个实体的某个不可变的id。例如,以Car
为例,你可以使用车牌号作为id.Equatable
: 满足Equatable
能帮助RxDataSources
判断哪个cell已经改变,从而给这些cells增加动画。意思是,Car
的任何属性改变,都是触发这个cel的 reload 动画
安装
我们尽可能的保持API的稳定,但是也不一定/狗头
CocoaPods
Podfile
pod 'RxDataSources', '~> 4.0'
Carthage
Cartfile
github "RxSwiftCommunity/RxDataSources" ~> 4.0
Swift Package Manager
创建一个 Package.swift
文件
import PackageDescription
let package = Package(
name: "SampleProject",
dependencies: [
.package(url: "https://github.com/RxSwiftCommunity/RxDataSources.git", from: "4.0.0")
]
)
如果你使用Xcode 11或者更高的版本,去 File / Swift Packages / Add Package Dependency...然后将Repo URL输如 https://github.com/RxSwiftCommunity/RxDataSources.git,然后按照说明操作。
原编辑时间 2021-02-04 15:46