You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MVVM模式下点击删除按钮删除UITableView单元格并更新列表的实现

实现MVVM模式下UITableView的单元格删除功能

看起来你已经搭好了MVVM的基础框架,接下来咱们一步步完善删除功能,严格遵循MVVM的职责分离原则——ViewModel处理数据逻辑,ViewController专注UI更新。

第一步:补全ViewModel的删除逻辑

首先要给ViewModel添加删除数据的方法,同时得加个通知UI更新的机制(这里用闭包回调最直接,你也可以用Delegate或Combine),还要做数据安全校验避免数组越界。

修改后的ViewModel代码如下:

class ViewModel: NSObject {
    var datasourceModel: DataSourceModel
    // 新增闭包,用来通知ViewController数据已变动
    var dataDidChange: (() -> Void)?
    
    init(withdatasource newDatasourceModel: DataSourceModel) {
        datasourceModel = newDatasourceModel
        super.init()
    }
    
    func datafordisplay(atindex indexPath: IndexPath) -> Model {
        // 加个安全判断,防止数组越界崩溃
        guard let dataList = datasourceModel.dataListArray, indexPath.row < dataList.count else {
            // 业务上可以返回默认Model,这里用fatalError提醒开发者注意
            fatalError("索引超出数据范围")
        }
        return dataList[indexPath.row]
    }
    
    // 新增删除数据的方法
    func deleteItem(at indexPath: IndexPath) {
        guard var dataList = datasourceModel.dataListArray, indexPath.row < dataList.count else {
            return
        }
        // 删除对应位置的数据
        dataList.remove(at: indexPath.row)
        datasourceModel.dataListArray = dataList
        // 通知UI层更新
        dataDidChange?()
    }
    
    // 新增获取数据总数的方法,方便TableView获取行数
    func numberOfItems() -> Int {
        return datasourceModel.dataListArray?.count ?? 0
    }
}

第二步:在ViewController中处理删除交互与UI更新

假设你的自定义Cell里有删除按钮,先给Cell添加点击回调,再在ViewController里绑定ViewModel和处理表格更新。

1. 给自定义Cell添加删除回调

class CustomTableViewCell: UITableViewCell {
    @IBOutlet weak var deleteButton: UIButton!
    // 用闭包传递删除按钮点击事件
    var deleteAction: (() -> Void)?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        deleteButton.addTarget(self, action: #selector(deleteButtonTapped), for: .touchUpInside)
    }
    
    @objc private func deleteButtonTapped() {
        deleteAction?()
    }
}

2. 在ViewController中绑定逻辑

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var tableView: UITableView!
    var viewModel: ViewModel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
        // 绑定ViewModel的数据更新回调
        viewModel.dataDidChange = { [weak self] in
            self?.tableView.reloadData()
        }
    }
    
    // MARK: - UITableView DataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel.numberOfItems()
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomTableViewCell
        let model = viewModel.datafordisplay(atindex: indexPath)
        cell.textLabel?.text = model.name // 假设你的Model有name属性
        // 绑定Cell的删除点击事件
        cell.deleteAction = { [weak self, weak viewModel] in
            guard let self = self, let viewModel = viewModel else { return }
            // 调用ViewModel删除数据
            viewModel.deleteItem(at: indexPath)
            // 用动画删除单元格,比reloadData更友好
            tableView.deleteRows(at: [indexPath], with: .automatic)
        }
        return cell
    }
}

一些细节提醒

  • 弱引用:闭包里一定要用[weak self]和[weak viewModel],避免循环引用导致内存泄漏。
  • 数据安全:所有涉及数组索引的地方都要做合法性判断,防止崩溃。
  • UI更新优化:单个单元格删除用deleteRows带动画,体验更好;批量删除再考虑用reloadData。
  • 职责分离:ViewModel永远不要直接操作TableView,所有UI操作都放在ViewController里,严格遵守MVVM的设计思想。

内容的提问来源于stack exchange,提问作者robbieroberts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:14:18