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

如何从自定义TableViewCell刷新数据并更新CartViewController?

解决方案:在CartTableViewCell中更新CartViewController

我来给你几种常用的实现方式,都是iOS开发里组件间通信的经典方案,你可以根据场景选择:

1. 闭包(Closure)—— 简洁直观的轻量通信

这种方式代码量少,适合Cell和ViewController这种直接的父子组件通信,逻辑清晰。

步骤:

  • 在CartTableViewCell里定义一个闭包属性,用来传递删除成功的事件
  • 在CartViewController的cellForRowAt方法中,给闭包赋值,处理具体的更新逻辑
  • 删除请求成功后调用闭包,通知VC更新

修改CartTableViewCell:

class CartTableViewCell: UITableViewCell {
    // 定义可选闭包,避免未赋值导致崩溃
    var onDeleteSuccess: (() -> Void)?
    
    @IBAction func buttonDeleteAction(_ sender: UIButton) {
        // 先做安全校验,避免空值崩溃
        guard let productId = label.text, let token = token else { return }
        let url = "http://aaaaaa/cart/\(productId)/del"
        let headers: HTTPHeaders = ["Accept":"application/json","Authorization":"Bearer \(token)"]
        
        Alamofire.request(url, method: .get, headers: headers).responseJSON { response in
            switch response.result {
            case .success(let value):
                let json = JSON(value)
                print("delete json ",json)
                let success = json["success"].boolValue
                print(success)
                if success {
                    // 调用闭包通知VC执行更新
                    self.onDeleteSuccess?()
                }
            case .failure(let error):
                print(error)
            }
        }
    }
}

在CartViewController中配置闭包:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CartTableViewCell", for: indexPath) as! CartTableViewCell
    
    // 这里配置cell的其他内容,比如给label赋值等...
    
    // 绑定闭包,处理删除成功后的刷新逻辑
    cell.onDeleteSuccess = { [weak self] in
        // 注意用weak self避免循环引用
        guard let self = self else { return }
        // 1. 先更新数据源(假设cartItems是你的购物车数据数组)
        self.cartItems.remove(at: indexPath.row)
        // 2. 刷新表格
        self.tableView.reloadData()
        // 或者如果需要从服务器重新拉取最新数据,就调用你的获取购物车列表接口
        // self.fetchCartList()
    }
    
    return cell
}

2. 代理模式(Delegate)—— iOS经典通信方式

代理是iOS里标准的组件解耦通信方式,适合逻辑更复杂、需要传递更多参数的场景。

步骤:

  • 定义一个代理协议,声明删除成功的方法
  • 在CartTableViewCell中添加代理属性
  • 让CartViewController遵守该协议并实现代理方法
  • 删除成功后调用代理方法通知VC

定义代理协议:

// 建议放在CartTableViewCell文件顶部
protocol CartTableViewCellDelegate: AnyObject {
    func cartTableViewCellDidDeleteSuccess(_ cell: CartTableViewCell)
}

修改CartTableViewCell:

class CartTableViewCell: UITableViewCell {
    // 用weak修饰避免循环引用
    weak var delegate: CartTableViewCellDelegate?
    
    @IBAction func buttonDeleteAction(_ sender: UIButton) {
        guard let productId = label.text, let token = token else { return }
        let url = "http://aaaaaa/cart/\(productId)/del"
        let headers: HTTPHeaders = ["Accept":"application/json","Authorization":"Bearer \(token)"]
        
        Alamofire.request(url, method: .get, headers: headers).responseJSON { response in
            switch response.result {
            case .success(let value):
                let json = JSON(value)
                print("delete json ",json)
                let success = json["success"].boolValue
                print(success)
                if success {
                    // 通知代理执行更新
                    self.delegate?.cartTableViewCellDidDeleteSuccess(self)
                }
            case .failure(let error):
                print(error)
            }
        }
    }
}

让CartViewController遵守并实现代理:

// 给类添加协议遵守
class CartViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, CartTableViewCellDelegate {
    
    // ...其他已有代码
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CartTableViewCell", for: indexPath) as! CartTableViewCell
        // 设置代理
        cell.delegate = self
        // 配置cell内容...
        return cell
    }
    
    // 实现代理方法
    func cartTableViewCellDidDeleteSuccess(_ cell: CartTableViewCell) {
        // 通过cell获取对应的indexPath
        guard let indexPath = tableView.indexPath(for: cell) else { return }
        // 更新数据源并刷新表格
        cartItems.remove(at: indexPath.row)
        tableView.reloadData()
        // 或者重新请求最新数据
        // fetchCartList()
    }
}

3. 通知中心(NotificationCenter)—— 跨组件通用方案

如果你的更新逻辑需要通知多个组件,或者Cell和VC的层级比较深,可以用通知中心,但如果只是Cell和VC之间的通信,前两种方案更高效、耦合度更低。

步骤:

  • 删除成功后发送自定义通知
  • 在VC中监听该通知并处理更新

在CartTableViewCell中发送通知:

if success {
    // 可以携带productId等参数,方便VC处理
    NotificationCenter.default.post(
        name: NSNotification.Name("CartItemDeletedSuccess"),
        object: nil,
        userInfo: ["productId": productId]
    )
}

在CartViewController中监听通知:

override func viewDidLoad() {
    super.viewDidLoad()
    // ...其他代码
    // 添加通知监听
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleCartItemDeleted(_:)),
        name: NSNotification.Name("CartItemDeletedSuccess"),
        object: nil
    )
}

// 处理通知的方法
@objc func handleCartItemDeleted(_ notification: Notification) {
    // 从userInfo中取出参数
    if let productId = notification.userInfo?["productId"] as? String {
        // 根据productId移除对应的数据
        cartItems.removeAll { $0.id == productId }
        tableView.reloadData()
    }
    // 或者直接重新请求数据
    // fetchCartList()
}

// 记得在销毁时移除监听,避免内存泄漏
deinit {
    NotificationCenter.default.removeObserver(self)
}

以上三种方案里,闭包和代理是最推荐的,因为它们的耦合度低,逻辑清晰,适合Cell和VC这种直接的关联场景;通知中心更适合跨多个组件的通信场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:35:14