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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:41:26