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
相关产品推荐
相关产品推荐

