如何在Table View Cell内部实现Table View刷新或单元格自删除?
在Table View Cell中实现自定义删除按钮的两种方案
不建议让Table View Cell直接持有并刷新父Table View(耦合度太高,违反MVC设计原则),更合理的做法是通过代理模式或闭包回调让Cell通知ViewController执行删除操作,以下是具体实现:
方案一:代理模式
1. 定义Cell的代理协议
在你的自定义Cell类中声明协议,约定删除行为:
// 自定义Cell类 import UIKit protocol CustomTableViewCellDelegate: AnyObject { func cellDidTapDeleteButton(_ cell: CustomTableViewCell) } class CustomTableViewCell: UITableViewCell { // 声明代理属性,必须用weak避免循环引用 weak var delegate: CustomTableViewCellDelegate? // 自定义删除按钮的IBAction @IBAction func deleteButtonTapped(_ sender: UIButton) { // 通知代理执行删除逻辑 delegate?.cellDidTapDeleteButton(self) } }
2. 在ViewController中实现代理逻辑
让Table View所在的ViewController遵守协议,并在代理方法中完成数据源删除和Table View刷新:
// Table View所在的ViewController class ViewController: UIViewController, UITableViewDataSource, CustomTableViewCellDelegate { var dataSource: [String] = ["数据1", "数据2", "数据3"] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomCell") } // UITableViewDataSource方法 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataSource.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomTableViewCell // 设置代理 cell.delegate = self cell.textLabel?.text = dataSource[indexPath.row] return cell } // 实现代理方法 func cellDidTapDeleteButton(_ cell: CustomTableViewCell) { // 获取当前Cell对应的indexPath guard let indexPath = tableView.indexPath(for: cell) else { return } // 删除数据源中的对应数据 dataSource.remove(at: indexPath.row) // 刷新Table View,推荐用deleteRows更流畅 tableView.deleteRows(at: [indexPath], with: .automatic) // 如果不需要动画,也可以用tableView.reloadData() } }
方案二:闭包(Block)回调
这种方式比代理更简洁,适合简单的回调场景:
1. 在Cell中定义闭包属性
// 自定义Cell类 class CustomTableViewCell: UITableViewCell { // 定义删除回调闭包,参数为当前Cell var deleteAction: ((UITableViewCell) -> Void)? @IBAction func deleteButtonTapped(_ sender: UIButton) { // 触发闭包 deleteAction?(self) } }
2. 在ViewController中绑定闭包逻辑
// Table View所在的ViewController class ViewController: UIViewController, UITableViewDataSource { var dataSource: [String] = ["数据1", "数据2", "数据3"] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomCell") } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataSource.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomTableViewCell cell.textLabel?.text = dataSource[indexPath.row] // 绑定闭包,处理删除逻辑 cell.deleteAction = { [weak self] cell in guard let self = self, let indexPath = self.tableView.indexPath(for: cell) else { return } self.dataSource.remove(at: indexPath.row) self.tableView.deleteRows(at: [indexPath], with: .automatic) } return cell } }
注意事项
- 无论用哪种方式,都要避免Cell直接持有ViewController或Table View的强引用,防止内存泄漏(比如闭包中用
[weak self],代理用weak修饰)。 - 优先使用
deleteRows(at:with:)而非reloadData(),前者会带动画效果,用户体验更好。
内容的提问来源于stack exchange,提问作者code_relic
相关产品推荐
相关产品推荐

