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模式的结构和实现方法,包括数据模型、视图、视图模型的创建和数据绑定,以及命令的实现和事件通知机制。
|
5月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
5月前
|
数据处理 开发者 C#
WPF数据绑定实战:从零开始,带你玩转数据与界面同步,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据绑定是核心技能之一,它能实现界面元素与数据源的同步更新。本文详细介绍了WPF数据绑定的概念与实现方法,包括属性绑定、元素绑定及路径绑定等技术,并通过示例代码展示了如何创建数据绑定。通过数据绑定,开发者不仅能简化代码、提高可维护性,还能提升用户体验。无论初学者还是有经验的开发者,都能从中受益,更好地掌握WPF数据绑定技巧。
118 0
|
5月前
|
容器 C# 开发者
XAML语言大揭秘:WPF标记的魅力所在,让你轻松实现界面与逻辑分离,告别复杂代码!
【8月更文挑战第31天】XAML提供了一种直观且易于维护的界面设计方式,使得开发者可以专注于逻辑和业务代码的编写,而无需关心界面细节。通过数据绑定、布局管理和动画效果等特性,XAML可以实现丰富的界面交互和视觉效果。在实际开发过程中,开发者应根据具体需求选择合适的技术方案,以确保应用程序能够满足用户的需求。希望本文的内容能够帮助您在WPF应用程序开发中更好地利用XAML语言。
54 0
|
存储 数据安全/隐私保护
RxSwift+MVVM项目实战-登录功能实现
RxSwift+MVVM项目实战-登录功能实现
268 0
|
C#
2000条你应知的WPF小姿势 基础篇<57-62 依赖属性进阶>
2000条你应知的WPF小姿势 基础篇<57-62 依赖属性进阶>
57 0
RxSwift+MVVM项目实战-单分组UITableView的使用
RxSwift+MVVM项目实战-单分组UITableView的使用
266 0
|
存储 Swift
RxSwift+MVVM项目实战-多分组UITableView结合RxDataSources的使用
RxSwift+MVVM项目实战-多分组UITableView结合RxDataSources的使用
361 0
RxSwift+MVVM项目实战-多分组UITableView+RxDataSources+MJRefresh的使用
RxSwift+MVVM项目实战-多分组UITableView+RxDataSources+MJRefresh的使用
159 0
|
JSON HandyJSON Swift
RxSwift+MVVM项目实战-多分组TableView+MJRefresh+RxAlamofire+HandyJSON的使用
RxSwift+MVVM项目实战-多分组TableView+MJRefresh+RxAlamofire+HandyJSON的使用
349 0

热门文章

最新文章