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

Swift中CartCell类型无navigationController成员报错解决及滑动删除后返回上页实现

解决CartCell中调用navigationController报错的问题

问题根源

你碰到的报错"Value of type 'CartCell' has no member 'navigationController'"其实很好理解:navigationController是UIViewController的专属属性,UITableViewCell本身并没有这个成员,所以直接在Cell类里调用肯定会触发错误。

可行解决方案

我们需要把返回上页的操作交给持有导航控制器的ViewController来处理,这里给你推荐几种贴合iOS开发最佳实践的方案:

方案1:扩展闭包回调(适配你现有代码结构)

你已经在使用updatePrice闭包做价格更新,那可以直接扩展闭包的职责,或者新增一个专门的回调来通知ViewController执行返回:

  1. 先在CartCell类里新增一个返回操作的闭包属性:
class CartCell: UITableViewCell {
    // 保留原有价格更新闭包
    var updatePrice: ((Bool) -> Void)?
    // 新增返回上页的回调闭包
    var triggerPopAction: (() -> Void)?
    
    // ... 你的其他已有代码
}
  1. 修改CartCell删除方法里的返回逻辑,替换原来的navigationController调用:
self.updatePrice = { [weak self] isUpdate in
    guard let self = self else { return }
    if arrayGlobleCart.count == 0 {
        // 触发闭包,把返回操作交给ViewController处理
        self.triggerPopAction?()
    }
}
  1. 在创建CartCell的ViewController(也就是你的购物车列表VC)中,给这个闭包赋值:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CartCell", for: indexPath) as! CartCell
    // ... 其他cell配置代码
    
    // 绑定返回操作的闭包,在这里安全调用navigationController
    cell.triggerPopAction = { [weak self] in
        self?.navigationController?.popViewController(animated: true)
    }
    
    return cell
}

方案2:使用代理模式(适合多回调场景)

如果你的Cell有多个需要通知VC的事件,代理模式会让代码结构更清晰:

  1. 定义一个代理协议:
protocol CartCellDelegate: AnyObject {
    func cartCellDidNeedPop(_ cell: CartCell)
}
  1. 在CartCell中添加代理属性:
class CartCell: UITableViewCell {
    weak var delegate: CartCellDelegate?
    // ... 其他代码
}
  1. 在删除方法中调用代理方法:
self.updatePrice = { [weak self] isUpdate in
    guard let self = self else { return }
    if arrayGlobleCart.count == 0 {
        self.delegate?.cartCellDidNeedPop(self)
    }
}
  1. 在ViewController中遵守并实现代理:
// 让购物车VC遵守协议
class CartListViewController: UIViewController, CartCellDelegate {
    // ... 其他代码
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CartCell", for: indexPath) as! CartCell
        cell.delegate = self
        // ... 其他配置
        return cell
    }
    
    // 实现代理方法,处理返回逻辑
    func cartCellDidNeedPop(_ cell: CartCell) {
        navigationController?.popViewController(animated: true)
    }
}

方案3:通过响应者链查找VC(应急方案,不推荐长期使用)

你可以通过遍历Cell的响应者链找到对应的ViewController,但这种方式耦合度高,不利于维护:

extension UIView {
    func findParentViewController() -> UIViewController? {
        if let vc = next as? UIViewController {
            return vc
        } else if let nextView = next as? UIView {
            return nextView.findParentViewController()
        }
        return nil
    }
}

然后在CartCell中使用:

self.updatePrice = { [weak self] isUpdate in
    guard let self = self else { return }
    if arrayGlobleCart.count == 0 {
        self.findParentViewController()?.navigationController?.popViewController(animated: true)
    }
}

额外优化提示

  • 闭包中记得添加[weak self]避免循环引用,防止内存泄漏;
  • 检查购物车总价为0的逻辑,建议直接计算总价(比如遍历所有商品求和),而不是仅判断数组为空,避免出现数组有元素但总价为0的遗漏场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 07:34:08