本文主要介绍利用RxSwift+MVVM
实现只有一个分组列表的添加、删除、移动功能,实现效果如图(文末附源码):
EditModel
title
:用于cell
上展示的标题;
index
:用于cell
上展示的随机数;
class EditModel { var title: String? var index: Int init(title: String?) { self.title = title self.index = Self.random } static var random: Int { Int(arc4random() % 10000) } }
EditCellViewModel
title
:用于将处理后的标题绑定到cell
的UI
控件上;
class EditCellViewModel: NSObject { var title = BehaviorRelay<String?>(value: nil) init(model: EditModel) { self.title.accept("\(model.title ?? "") - 随机数 - \(model.index)") } }
EditTableViewCell
主要是cell
内部子控件的布局,以及绑定数据到UI
func bind(to viewModel: EditCellViewModel) { if let _label = textLabel { viewModel.title.bind(to: _label.rx.text).disposed(by: disposeBag) } }
EditOperationType
存储用于操作的事件类型,并存储数据;
enum EditOperationType { case refresh //刷新 case delete(items: IndexPath) //删除 case move(event: ItemMovedEvent) //移动 case add(cellModel: EditCellViewModel) //添加 }
EditViewModel
refresh
:接收刷新的事件;
moved
:tableView
移动的事件;
delete
:tableView
的删除事件;
add
:添加事件;
将input
中的各种事件通过map
转换为对应的操作类型,并保存数据,通过merge
操作对dataSource
进行对应的处理,并抛出到外界绑定到tableView
的数据源上,以更新数据;
class EditViewModel { private let disposeBag = DisposeBag() private lazy var dataSource: [EditCellViewModel] = { var _items = [EditCellViewModel]() for index in 0...5 { let a1 = EditModel.random _items.append(EditCellViewModel(model: EditModel(title: "初识标题"))) } return _items }() struct Input { let refresh: Observable<Void> let moved: ControlEvent<ItemMovedEvent> let delete: ControlEvent<IndexPath> let add: Observable<Void> } struct Output { let items: BehaviorRelay<[EditCellViewModel]> } func transform(input: Input) -> Output { let dataSource = BehaviorRelay<[EditCellViewModel]>(value: []) let refresh = input.refresh.map({ EditOperationType.refresh }) let delete = input.delete.map({ EditOperationType.delete(items: $0) }) let move = input.moved.map({ EditOperationType.move(event: $0)}) let add = input.add.map({ EditOperationType.add(cellModel: EditCellViewModel(model: EditModel(title: "添加标题"))) }) Observable.of(refresh, delete, move, add).merge().map {[weak self] type -> [EditCellViewModel] in guard let `self` = self else { return [] } switch type { case .delete(let indexPath): self.dataSource.remove(at: indexPath.row) break case .move(let itemMove): self.dataSource.insert(self.dataSource.remove(at: itemMove.sourceIndex.row), at: itemMove.destinationIndex.row) break case .refresh: break case .add(cellModel: let cellModel): self.dataSource.append(cellModel) break } return self.dataSource }.bind(to: dataSource).disposed(by: disposeBag) return Output(items: dataSource) } }
EditViewController
绑定ViewModel
数据,以及监听事件并做出响应;
private func bindToViewModel() { let output = viewModel.transform(input: RootViewModel.Input(refresh: Observable.of(()), moved: tableView.rx.itemMoved, delete: tableView.rx.itemDeleted, add: addItem.rx.tap.asObservable())) output.items.asDriver().drive(tableView.rx.items(cellIdentifier: cellId, cellType: EditTableViewCell.self)) {row, viewModel, cell in cell.bind(to: viewModel) }.disposed(by: disposeBag) tableView.rx.modelSelected(EditCellViewModel.self).subscribe {[weak self] (cellModel) in Logger(cellModel.element?.title.value) }.disposed(by: disposeBag) tableView.rx.itemSelected.subscribe {[weak tableView] in tableView?.deselectRow(at: $0, animated: true) }.disposed(by: disposeBag) editItem.rx.tap.map({[unowned self] in !self.tableView.isEditing }).bind(to: tableView.rx.isCanEditing).disposed(by: disposeBag) Observable.of(Observable.just(()), editItem.rx.tap.asObservable()).merge().map({[unowned self] _ in !self.tableView.isEditing }).bind(to: editItem.rx.isCanEditing).disposed(by: disposeBag) tableView.rx.setDelegate(self).disposed(by: disposeBag) }
复制搜一搜分享收藏划线