RxSwift+MVVM项目实战-单分组UITableView添加、删除、移动功能

简介: RxSwift+MVVM项目实战-单分组UITableView添加、删除、移动功能

本文主要介绍利用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:用于将处理后的标题绑定到cellUI控件上;

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:接收刷新的事件;

movedtableView移动的事件;

deletetableView的删除事件;

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)
}


复制搜一搜分享收藏划线


相关文章
|
4月前
|
设计模式 前端开发 C#
WPF 项目中 MVVM模式 的简单例子说明
本文通过WPF项目中的加法操作示例,讲解了MVVM模式的结构和实现方法,包括数据模型、视图、视图模型的创建和数据绑定,以及命令的实现和事件通知机制。
|
存储 数据安全/隐私保护
RxSwift+MVVM项目实战-登录功能实现
RxSwift+MVVM项目实战-登录功能实现
263 0
|
8月前
|
JavaScript 小程序 Android开发
【经验分享】如何实现自定义的actionSheet组件
【经验分享】如何实现自定义的actionSheet组件
130 6
RxSwift+MVVM项目实战-单分组UITableView的使用
RxSwift+MVVM项目实战-单分组UITableView的使用
263 0
|
存储 Swift
RxSwift+MVVM项目实战-多分组UITableView结合RxDataSources的使用
RxSwift+MVVM项目实战-多分组UITableView结合RxDataSources的使用
356 0
RxSwift+MVVM项目实战-多分组UITableView+RxDataSources+MJRefresh的使用
RxSwift+MVVM项目实战-多分组UITableView+RxDataSources+MJRefresh的使用
157 0
|
JSON HandyJSON Swift
RxSwift+MVVM项目实战-多分组TableView+MJRefresh+RxAlamofire+HandyJSON的使用
RxSwift+MVVM项目实战-多分组TableView+MJRefresh+RxAlamofire+HandyJSON的使用
347 0
|
前端开发
前端学习笔记202305学习笔记第二十三天-树形控件和路由分析
前端学习笔记202305学习笔记第二十三天-树形控件和路由分析
52 0
|
前端开发
前端学习笔记202305学习笔记第二十三天-树形控件和路由分析2
前端学习笔记202305学习笔记第二十三天-树形控件和路由分析2
69 0
|
前端开发
前端学习笔记202305学习笔记第二十三天-树形控件和路由分析
前端学习笔记202305学习笔记第二十三天-树形控件和路由分析
66 0