记录 RxDataSource 的简单使用过程, 特别是用在 TableView 的时候.
RxDataSource 的简单使用
用到的库: RxDataSources.
整个使用流程如下所示:
-
定义 Section 和 Cell 的数据结构:
swift/// Section 模型 struct AddNewAddressViewCellNormalSection { var header: String var items: [AddNewAddressViewCellType] } /// 扩展 Section 模型, 让其遵守 SectionModelType 协议, 以便数据源使用 extension AddNewAddressViewCellNormalSection: SectionModelType { init(original: AddNewAddressViewCellNormalSection, items: [AddNewAddressViewCellType]) { self = original self.items = items } } /// 多种类型 Cell 数据模型定义 enum AddNewAddressViewCellType { case textAndTextField(String, String, String, Bool) case textAndSwitch(String, Bool) }上面代码中定义了一个 TableView 中的 Section 模型, 这个模型必须要有的存储属性是 items, 其中的元素类型就是 Cell 的模型.
-
定义好数据结构后, 就可以组装数据了. 数据可以通过 Variable 来提供(当然也可以用
PublishSubject等 Subject, 比如要网络获取数据的情况):swiftlet celldata = Variable<[AddNewAddressViewCellNormalSection]>([ // section0 AddNewAddressViewCellNormalSection(header: "", items: [.textAndTextField("收货人", "", "输入收件人姓名", false), .textAndTextField("手机号码", "", "输入收件人手机号", false), // section1 AddNewAddressViewCellNormalSection(header: "", items: [.textAndSwitch("设置为默认收货地址", false)]) ])上面的数据中定义了两个 section, 且每个 section 中使用的都是不同的 cell 数据模型.
-
设置 TableView 的数据源和代理:
swift// 绑定数据源 viewModel.celldata.asObservable() .bind(to: _tableView.rx.items(dataSource: getDataSource())).disposed(by: _disposeBag) // 设置代理 _tableView.rx.setDelegate(self).disposed(by: _disposeBag) // 其中的 getDataSource() 方法如下所示: private func getDataSource() -> RxTableViewSectionedReloadDataSource<AddNewAddressViewCellNormalSection> { return RxTableViewSectionedReloadDataSource<AddNewAddressViewCellNormalSection>( configureCell: { dataSource, tableView, indexPath, item in switch item { case .textAndTextField(let labelText, let content, let placeHolder, let showClosure): // dequeue cell 并根据 item 配置 cell case .textAndSwitch(let labelText, let isOn): // dequeue cell 并根据 item 配置 cell } }) }
通过上述方式设置后, 如果要更新数据, 只要在之前创建的 celldata (类型是 Subject 中的一种) 上更新最新数据, 则 TableView 便可以同步更新.
若 tableView 有其他的设置, 可以在 tableView 上直接进行, 也可以在代理中处理:
_tableView.isScrollEnabled = false _tableView.tableFooterView = UIView() _tableView.backgroundColor = .clear _tableView.rowHeight = 45 _tableView.register(AddNewAddressViewEditableCell.self, forCellReuseIdentifier: AddNewAddressViewEditableCell.reuseID) _tableView.register(AddNewAddressViewSwitchableCell.self, forCellReuseIdentifier: AddNewAddressViewSwitchableCell.reuseID)
注意数据源中的类型是 Section 数组, 而非 Section 类型! 否则编译会报错.
如果要将 cell 上的一些控件点击都绑定到控制器对应的视图模型上, 则需要在配置数据源的时候进行处理.