RxSwift - 实现一个MVVM架构的TableView

RxSwift - 实现一个MVVM架构的TableView

前沿

MVVM架构在在实际开发中被广泛应用,它让代码结构清晰美观,易于阅读维护,同时也弥补了MVC结构中Controller臃肿的问题

今天来实现一个基于RxSwift的基础TableView页面

效果:使用RxSwift,将ViewModel进行绑定,实现动态修改数据时更新UI

MVVM架构的Tableview

目录结构

以下是目录结构

-w400

目录由ViewModelViewModel三个文件夹组成

1、模型(Model)

Model文件夹下新建Product文件

import Foundation

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

模型简单表示了一个商品的

2、视图模型(ViewModel)

ViewModel文件夹下新建ProductViewModel文件。它相当于是ViewModel的桥梁,在ViewModel中会有相应的获取数据以及处理数据的方法,然后将数据传输到View

import Foundation
import RxSwift

class ProductViewModel {
    // PublishSubject: 只会发送新的事件给订阅者,订阅之前的事件不会发送
    // BehaviorSubject: 会保持最新的值,并将其发送给新的订阅者
    let items = PublishSubject<[Product]>()
//  let items = BehaviorSubject<[Product]>(value: [])
    
    var productArray: [Product]!
    
    func fetchProductList() {
        // 在这里可以做网络请求
        // 咱们就直接用假数据
        productArray = [
            Product(imgName: "apple", name: "apple", price: "10"),
            Product(imgName: "banana", name: "banana", price: "5"),
            Product(imgName: "pear", name: "pear", price: "4"),
            Product(imgName: "watermelon", name: "watermelon", price: "3"),
            Product(imgName: "mango", name: "mango", price: "8")
        ]
        
        items.onNext(productArray)
//        items.onCompleted()
    }
    
    func addData() {
        productArray.append(Product(imgName: "peach", name: "peach", price: "7"))
        items.onNext(productArray)
    }
}

该类中:

  • 定义了时间发布者items,使用PublishSubject类型
  • 定义获取数据的方法fetchProductList(),获取完数据后,使用onNext将事件发布出去。代码中注释掉onCompleted(),是因为想要实现后续数据更新的操作,onCompleted会终止序列,使其不再接收新的元素。
  • 定义addData()方法,界面中将通过点击按钮模拟增加数据操作

3、视图(View)

View层,首先有个简单的CellProductTableViewCell,它有一个数据有属性item,赋值时进行UI内容样式设置

import UIKit

class ProductTableViewCell: UITableViewCell {
    
    var item: Product? = nil {
        didSet{
            textLabel?.text = item?.name
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

接下来是ViewController

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController, UIScrollViewDelegate {
    
    private let bag = DisposeBag()
    private let viewModel = ProductViewModel()
    
    lazy var tableView: UITableView = {
        let tableView = UITableView(frame: view.bounds, style: UITableView.Style.grouped)
        view.addSubview(tableView)
        
        return tableView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.rx.setDelegate(self).disposed(by: bag)
        bindTableView()
        
        let btn:UIButton = UIButton(type: .system)
        btn.frame = CGRectMake(10, view.frame.size.height - 80, view.frame.size.width - 20, 50)
        btn.backgroundColor = .lightGray
        btn.setTitle("addData", for: UIControl.State.normal)
        btn.rx.tap
            .subscribe(onNext: { [unowned self] in
            self.viewModel.addData()
        }).disposed(by: bag)

        view.addSubview(btn)
    }
    
    private func bindTableView() {
        tableView.register(ProductTableViewCell.self, 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()
    }
}
  • 定义private let bag = DisposeBag(),作用就是在合适的时机自动调用这些 Disposable 对象的 dispose() 方法,释放资源,避免内存泄漏
  • 持有ViewModelprivate let viewModel = ProductViewModel()
  • 初始化tableView
  • viewDidLoad()中,指定了tableView代理为self,然后将viewModelitems事件绑定到tableView,即将数据源绑定到表视图行。同时订阅了选中某个模型的事件modelSelected,即选中某个Cell的事件。(使用RxCocoa提供的方法实现)
  • 增加一个按钮,点击时调用viewModel.addData()方法,动态修改数据源。因为已将tableView绑定到数据源,视图也将动态刷新

界面效果

-w200

@oubijiexi

MVVM 是一种软件架构模式,它将应用程序分为三个部分:Model,View 和 ViewModel。在Qt中,可以使用QML语言实现MVVM架构。 以下是使用Qt的MVVM架构的步骤: 1. 定义模型(Model):定义数据模型,可以使用Qt的Model/View框架来实现。 2. 定义视图(View):使用QML语言定义视图,包括用户界面和交互逻辑。 3. 定义视图模型(ViewModel):使用JavaScript编写视图模型,它是一个中间层,连接视图和模型。它负责管理视图和模型之间的数据传输和转换。 4. 将视图(View)和视图模型(ViewModel)连接起来:在QML中使用绑定来连接视图和视图模型。这样,当视图模型中的数据发生变化时,视图会自动更新。 5. 将模型(Model)和视图模型(ViewModel)连接起来:在视图模型中使用信号和槽机制来连接模型和视图模型。这样,当模型中的数据发生变化时,视图模型会接收到信号,然后更新视图。 下面是一个简单的例子: ```qml import QtQuick 2.0 Item { property string name property int age property string address TextField { text: name onTextChanged: { viewmodel.updateName(text) } } TextField { text: age.toString() onTextChanged: { viewmodel.updateAge(parseInt(text)) } } TextField { text: address onTextChanged: { viewmodel.updateAddress(text) } } Connections { target: viewmodel onUpdateName: name = newName onUpdateAge: age = newAge onUpdateAddress: address = newAddress } } ``` 在这个例子中,我们定义了一个Item,它包含三个属性:name,age和address。我们使用三个TextField来显示这些属性,并且每当属性发生变化时,我们会调用视图模型中的相应函数来更新模型中的数据。 在视图模型中,我们定义了三个函数:updateName,updateAge和updateAddress,它们分别用于更新name,age和address。我们还定义了三个信号:onUpdateName,onUpdateAge和onUpdateAddress,用于将模型中的数据传递给视图。 ```javascript function ViewModel(model) { this.model = model; this.updateName = function(newName) { this.model.name = newName; this.onUpdateName(newName); } this.updateAge = function(newAge) { this.model.age = newAge; this.onUpdateAge(newAge); } this.updateAddress = function(newAddress) { this.model.address = newAddress; this.onUpdateAddress(newAddress); } signal onUpdateName(string newName) signal onUpdateAge(int newAge) signal onUpdateAddress(string newAddress) } var model = { name: "John", age: 30, address: "123 Main St." } var viewmodel = new ViewModel(model); ``` 在这个例子中,我们定义了一个ViewModel对象,它接收一个模型对象作为参数。我们在这个对象中实现了updateName,updateAge和updateAddress函数,并且定义了三个信号。当这些函数被调用时,它们会更新模型中的数据,并且发出相应的信号。 最后,我们创建了一个模型对象和一个视图模型对象,并将它们连接起来。 这只是一个简单的例子,但是它演示了如何使用Qt的MVVM架构实现一个简单的应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值