RxSwift 遇到tableView
let dataOB = BehaviorSubject.init(value: self.viewModel.dataArray)
// dataOB.bind(to: self.tableView.rx.items){(table,row,model) -> UITableViewCell in
// let cell = table.dequeueReusableCell(withIdentifier: self.resuseID)
// return cell as! LGTableViewCell
// }
dataOB.asObserver().bind(to: self.tableView.rx.items(cellIdentifier:self.resuseID,cellType: LGTableViewCell.self)){(row,model,cell) in
cell.setUIData(model as! LGModel)
}.disposed(by: disposeBag)
tableView.rx.itemSelected
.subscribe(onNext:{[weak self] index in
}).disposed(by: disposeBag)
tableView.rx.itemDeselected
.subscribe(onNext:{index in
}).disposed(by: disposeBag)
tableView.rx.itemMoved
.subscribe(onNext:{[weak self] (sourceIndex,destinationIndex) in
print("从\(sourceIndex)移动到\(destinationIndex)")
}).disposed(by: disposeBag)
- TableView的点击、复选、新增、删除、移动全部简洁实现
- RxSwift一旦遇上了TableView,根本不需要那些恶心的胶水代码
- delegate & dataSource的赋值直接免去
- 胶水代理以及数据源代理的实现(毕竟我们现在列表界面越来越多,胶水的代码的优化,太爽了)
- 我们所有的事件订阅都在相应地方,我们更容易管理
- 函数式回调导致我们的逻辑代码与功能代码绑定在一块,可读性更强
- cell高度可通过代理实现
extension LGRxViewController:UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
分组tableView
let tableViewDataSource = RxTableViewSectionedReloadDataSource<SectionModel<String,LGSectionModel>>(configureCell: { [weak self](dataSource, tab, indexPath, model) -> LGTableViewCell in
let cell = tab.dequeueReusableCell(withIdentifier: self?.resuseID ?? "resuseID_LGSectionViewController", for: indexPath) as! LGTableViewCell
cell.setUISectionData(model)
cell.selectionStyle = .none
return cell
},titleForHeaderInSection: { dataSource,index -> String in
// print("数据:\(dataSource.sectionModels[index].identity)")
return dataSource.sectionModels[index].model
})
/// 我们上次就是通过bind函数,这里我们变化一下
self.data.githubData.asDriver(onErrorJustReturn: [])
.drive(self.tableView.rx.items(dataSource: tableViewDataSource))
.disposed(by: self.disposeBag)
MVVM双向绑定
VC中:
override func viewDidLoad() {
super.viewDidLoad()
self.setupUI()
// 现在来一个需求:我们的输入框搜索 - 请求网络 - 下面tableView联动
// UI <-> model
self.searchBar.rx.text.orEmpty
.bind(to: self.viewModel.searchTextOB)
.disposed(by: disposeBag)
// 数据层绑定UI
self.viewModel.searchData.drive(self.tableView.rx.items){ (tableView, indexPath, model) -> LGTableViewCell in
let cell = tableView.dequeueReusableCell(withIdentifier: self.resuseID) as! LGTableViewCell
cell.nameLabel.text = model.name
cell.classLabel.text = model.url
return cell
}
.disposed(by: disposeBag)
// tittle绑定
self.viewModel.searchData.map { (array) -> String in
return "搜索到了 \(array.count) 条数据"
}
.drive(self.navigationItem.rx.title)
.disposed(by: disposeBag)
// 滑动减速绑定
self.tableView.rx.didEndDecelerating
.subscribe { [weak self] in
self?.searchBar.endEditing(true)
}.disposed(by: disposeBag)
}
- 这里就是我们RxSwift世界里的ViewController,这才是真正的轻量化的VC,至始至终都只做一件事:建立View与ViewModel之间的绑定依赖关系
- 通过我们搜索栏的响应,发送数据给我们的ViewModel,让它在它的世界里处理业务层,网络层数据的返回
- 通过ViewModel响应对外,达到数据绑定到UI的效果
- 在ViewModel里面我们运用RxSwift的高阶函数,处理逻辑
VM中
let searchTextOB = BehaviorSubject(value: "")
lazy var searchData: Driver<[LGReposityModel]> = {
return self.searchTextOB.asObserver()
.throttle(RxTimeInterval.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapFirst(LGComprehensiveViewModel.resposeData)
.asDriver(onErrorJustReturn: [])
}()
- UI事件搜索的响应传入,通过一个懒加载的数据返回
- 这个响应的序列通过throttle保证了相隔0.3秒发送一次事件
- distinctUntilChanged函数保证了带宽,直到搜索字眼变动的时候才请求
- flatMapFirst因为序列的序列,我们下沉请求,回调结果
- asDriver包装成Drive序列,保证状态共享,主线程调度,没有错误返回
或者直接用BehaviorRelay封装数据源,在VC中绑定tableview
网友评论