使用RXSwift撸一个MVVM架构的Tableview

5,423 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情


前言

又来撸RXSwift了

RXSwift能做的事很多,今天就来实现一个基本的Tableview。看一看RXSwift在实际开发中,有没有给我们提供便利。

还是先声明 咱们使用的版本是

pod 'RxSwift', '~> 5.0'
pod 'RxCocoa', '~> 5.0'

版本比较新,对应以前的版本,RXSwift有语法上的变化,注意

正文

咱们使用的是MVVM方式构建代码 先看目录

截屏2022-05-27 上午9.48.14.png

第一步: 模型(Model)

我们在Model文件夹下创建一个Product模型

import Foundation

struct Product {
    let imgName: String // 图
    let name: String// 名称
    let price: String// 价格
}

第二步: 视图模型(ViewModel)

咱们在 ViewModel 文件夹下创建一个 ProductViewModel 它的作用就是是 View 和 Model 之间的连接器,它可以将获取到的数据传输到 ViewController。

class ProductViewModel {
    
    let items = PublishSubject<[Product]>()
    
    func fetchProductList() {
            // 在这里可以做网络请求
            // 咱们就直接用假数据
            let productArray = [
                Product(imgName: "mac", name: "MacBook", price: "100"),
                Product(imgName: "iphone", name: "iPhone Xs", price: "100"),
                Product(imgName: "watch", name: "iWatch", price: "100"),
                Product(imgName: "ipad", name: "iPad", price: "100"),
                Product(imgName: "iphone", name: "iPhone X", price: "100")
            ]
        
        items.onNext(productArray)
        items.onCompleted()
    }
    
}

这里解释一下 PublishSubject: 只会发送新的事件给订阅者,订阅之前的事件不会发送。

第三步 视图(view)

咱们在view文件夹下创建ProductViewController 继承自 UIViewController (至于为什么ViewController是属于view层的,可以参考MVVM的架构模式)。

ProductViewController中 咱们来编写RXSwift的核心代码。

首先呢,要定义两个属性

private let bag = DisposeBag()
private let viewModel = ProductViewModel()

bag: 是和生命周期相关

viewModel: 就是视图模型拉

然后在viewDidLoad中设置tableview的 Delegate

override func viewDidLoad() {
        super.viewDidLoad()
        // 设置代理
        tableView.rx.setDelegate(self).disposed(by: bag)
        bindTableView()
    }

为什么不设置datasource呢?

往下看 ⬇️⬇️

bindTableView():就是将数据和tableview进行绑定

再来看bindTableView()里的代码

private func bindTableView() {
        tableView.register(UINib(nibName: "ProductTableViewCell", bundle: nil), forCellReuseIdentifier: "cellId")
        
        viewModel.items.bind(to: tableView.rx.items(cellIdentifier: "cellId", cellType: ProductTableViewCell.self)) { (row,item,cell) in
            cell.item = item
        }.disposed(by: bag)
        
        tableView.rx.modelSelected(Product.self).subscribe(onNext: { item in
            print("SelectedItem: \(item.name)")
        }).disposed(by: bag)
        
        viewModel.fetchProductList()
    }

第一步:先注册cell 。

第二步:将 viewModel.items 绑定到 tableView的cell上,,在RXSwift给的闭包中,进行 cell 的赋值操作,这样就省去了设置Datasource。

第三步:设置点击方法,同样使用RXSwift的方法modelSelected,将点击方法设置到tableview上。

第四步:请求接口(这里是直接拿假数据)。

到这里,就完成了设置tableview的 Datasource 和 绑定数据的事情,这样一看,确实比以前的代码量少了许多,还不错。

最后呢 在来看Delegate

Delegate比较简单,就只设置个高度就行,因为只是个简单Demo,就不搞别的了

extension ProductViewController: UITableViewDelegate {
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 150
    }
}

到这里,一个使用MVVM架构的Tableview就完成了(cell按需可以自己定义,这里就不写了)。

结语

总体来说,使用RXSwift来做Tableview还是比较迅速的,但是还是有一点,就是api不熟,查资料比较多。解决方式就是代码块,让你感觉飞起来。不过这个要平时的积累。