本文主要介绍利用RxSwift+MVVM
实现只有一个分组的列表,实现效果如图(文末附源码):
Model
title
:显示的标题
targetVC
:点击每个item
的时候,用作创建控制器以及跳转使用
class RootModel { var title: String? var targetVC: UIViewController.Type? init(title: String?, targetVC: UIViewController.Type) { self.title = title self.targetVC = targetVC } }
RootCellViewModel
用于将标题绑定到cell
的UI
控件上,以及获取跳转控制器
class RootCellViewModel: NSObject { var title = BehaviorRelay<String?>(value: nil) var targetVC = BehaviorRelay<UIViewController.Type?>(value: nil) init(model: RootModel) { self.title.accept(model.title) self.targetVC.accept(model.targetVC) } }
RootTableViewCell
主要是cell
内部子控件的布局,以及绑定数据到UI
func bind(to viewModel: RootCellViewModel) { if let _label = textLabel { viewModel.title.bind(to: _label.rx.text).disposed(by: disposeBag) } }
RootViewModel
Input.refresh
:接收刷新时机的事件
Output.items
:用于TableView
绑定内容
class RootViewModel { struct Input { let refresh: Observable<Void> } struct Output { let items: BehaviorRelay<[RootCellViewModel]> } func transform(input: Input) -> Output { let dataSource = BehaviorRelay<[RootCellViewModel]>(value: []) input.refresh.map {[weak self] (_) -> [RootCellViewModel] in return self?.dataSource ?? [] }.bind(to: dataSource).disposed(by: disposeBag) return Output(items: dataSource) } private var dataSource: [RootCellViewModel] { get { return [...] } } }
RootViewController
绑定ViewModel
数据,以及监听事件并做出响应
private func bindToViewModel() { let output = viewModel.transform(input: RootViewModel.Input(refresh: Observable.just(()))) //设置cell的数据源 output.items.asDriver().drive(tableView.rx.items(cellIdentifier: cellId, cellType: RootTableViewCell.self)) {row, viewModel, cell in cell.bind(to: viewModel) }.disposed(by: disposeBag) //cell点击事件直接可以拿到模型数据 tableView.rx.modelSelected(RootCellViewModel.self).subscribe {[weak self] (cellModel) in if let targetVC = cellModel.element?.targetVC.value { self?.navigationController?.pushViewController(targetVC.init(), animated: true) } }.disposed(by: disposeBag) //cell点击事件拿到indexPath tableView.rx.itemSelected.subscribe {[weak tableView] in tableView?.deselectRow(at: $0, animated: true) }.disposed(by: disposeBag) //可以利用它来遵守UITableViewDelegate协议,自己实现代理方法 tableView.rx.setDelegate(self).disposed(by: disposeBag) }
注意:tableView设置代理不可以再使用tableView.delegate = self
,而是使用tableView.rx.setDelegate(self)
,否则会抛出异常;
收藏划线