RxSwift 篇章已经接近尾声,回首这个历程很累但很充实:白天备课,晚上VIP上课!忙里偷闲写下了这个篇章。可以说:痛并快乐着
当我列出下面的列表的时候,突然发现好幸福,每一个篇章,都是自己坚持的成功,都是自己努力的收获,感谢自己每个凌晨的灵感,感谢陪我一起前行的我的周边人
就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!
一、首先面向开发我们看看RxSwift在TableView的应用
/// tableView -- RX
func setupTableViewRX() {
let dataOB = BehaviorSubject.init(value: self.viewModel.dataArray)
// 骚起来
// dataOB.bind(to: self.tableView.rx.items){(tabView,row,model) ->LGTableViewCell in
// let cell = tabView.dequeueReusableCell(withIdentifier: resuseID) as! LGTableViewCell
// cell.setUIData(model as! LGModel)
// return cell
// }.disposed(by: disposeBag)
dataOB.asObserver().bind(to: self.tableView.rx.items(cellIdentifier: resuseID, cellType: LGTableViewCell.self)){
(row,model,cell) in
cell.setUIData(model as! LGModel)
}.disposed(by: self.disposeBag)
// tableView点击事件
tableView.rx.itemSelected.subscribe(onNext: { [weak self](indexPath) in
print("点击\(indexPath)行")
self?.navigationController?.pushViewController(LGSectionViewController(), animated: true)
self?.tableView.deselectRow(at: indexPath, animated: true)
}).disposed(by: self.disposeBag)
// tableView复选点击事件
tableView.rx.itemDeselected.subscribe(onNext: { (indexPath) in
print("再次点击\(indexPath)行")
}).disposed(by: self.disposeBag)
// tableView移动事件
tableView.rx.itemMoved.subscribe(onNext: { [weak self] (sourceIndex,destinationIndex) in
print("从\(sourceIndex)移动到\(destinationIndex)")
self?.viewModel.dataArray.swapAt(sourceIndex.row, destinationIndex.row)
self?.loadUI(obSubject: dataOB)
}).disposed(by: self.disposeBag)
// tableView删除事件
tableView.rx.itemDeleted.subscribe(onNext: { [weak self](indexPath) in
print("点击删除\(indexPath)行")
self?.viewModel.dataArray.remove(at: indexPath.row)
self?.loadUI(obSubject: dataOB)
}).disposed(by: self.disposeBag)
// tableView新增事件
tableView.rx.itemInserted.subscribe(onNext: { [weak self](indexPath) in
print("添加数据在\(indexPath)行")
guard let model = self?.viewModel.dataArray.last else{
print("数据有问题,无法新增")
return
}
self?.viewModel.dataArray.insert(model, at: indexPath.row)
self?.loadUI(obSubject: dataOB)
}).disposed(by: self.disposeBag)
}
-
TableView
的点击、复选、新增、删除、移动
全部简洁实现 -
RxSwift
一旦遇上了TableView
,根本不需要那些恶心的胶水代码 -
delegate & dataSource
的赋值直接免去 - 胶水代理以及数据源代理的实现(毕竟我们现在列表界面越来越多,胶水的代码的优化,太爽了)
- 我们所有的事件订阅都在相应地方,我们更容易管理
- 函数式回调导致我们的逻辑代码与功能代码绑定在一块,可读性更强
二、分组的TableView
/// Rx 处理分组
func setupTableViewRX() {
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)
/// 跳转到网络相关Demo
self.tableView.rx.itemSelected.subscribe(onNext: { [weak self](indexPath) in
self?.navigationController?.pushViewController(LGNetworkViewController(), animated: true)
}).disposed(by: self.disposeBag)
}
-
RxCocoa
封装的dataSourcer
让我们爽的无法自拔 -
dataSource
的承担了整个数据源代理,并且强势封装了代理 - 数据层的响应直接绑定到了UI,让数据更简单传输
- 从上面的代码一眼就能看出,
RxSwift
让我们的开发更直接面向开发,让开发更容易
MVVM双向绑定
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
的高阶函数,处理逻辑
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
序列,保证状态共享,主线程调度,没有错误返回
static func resposeData(_ githunId: String) -> Observable<[LGReposityModel]> {
guard !githunId.isEmpty,let url = URL(string: "https://api.github.com/users/\(githunId)/repos") else {
return Observable.just([])
}
return URLSession.shared.rx.json(url: url)
.retry()
.observeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.map(LGComprehensiveViewModel.parseData)
}
- 通过上面的响应,这里封装网络
URLSession.shared.rx.json
,返回json - 为了保证请求网络在子线程,这里调用
observeOn
- 请求回来的数据还不是我们所想要的,这里
map
映射,下沉的序列化结果
static func parseData(_ json: Any) -> [LGReposityModel] {
guard let items = json as? [[String: Any]] else {return []}
guard let result = [LGReposityModel].deserialize(from: items) else { return [] }
return result as! [LGReposityModel]
}
- 这里就是普通的判空,然后通过
HandJSON
进行数据解析 - 返回的结果序列成模型数组,然后返回响应
- 响应层层下发,数据层层处理上升
- 根据外界的关系,完美实现双向绑定
完美实现联动,MVVM双向绑定加入RxSwift的身影也就更出色
- 当北京遇上西雅图
- 当爱情遇上婚姻
- 当兴趣遇上事业
- 当MVVM遇上RxSwift
- 我的天一切的一切都是那么的美好,安逸~~~舒服!!!
所有的努力都会在某一个时刻兑现,我们很多小伙伴都会感叹怎么还不来!你要知道:毋庸置疑,好的事情总会到来,当他来晚的时候也不失为一种惊喜
就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!
网友评论