RxSwiftCommunity / RxDataSources使用介绍

翻译自https://github.com/RxSwiftCommunity/RxDataSources

Table and Collection view data sources

特点

  • O(N)的算法计算差异
    • 这个算法假设所有的sections和items是唯一的,因此没有二义性
    • 在有二义性的情况下,没有动画刷新时自动回退  
  • 它使用附加的启发式来传送最少的命令给sections view
    • 尽管运行时间是线性的,但实际发送的命令数远少于线性
    • 最好(也可能)将更改的数量限制为一个小的数字,如果更改的数量朝着线性增长,只需进行正常的重新加载
  • 支持对你的item和section进行扩展
    • 仅仅扩展具有 IdentifiableTypeEquatable 的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通过简单的数据绑定机制来减轻负担.

  1. 把你的数据转换成Observable序列
  2. 使用如下之一将数据绑定到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

posted @ 2021-11-24 14:12  Rogn  阅读(795)  评论(0编辑  收藏  举报