Swift中CartCell类型无navigationController成员报错解决及滑动删除后返回上页实现
问题根源
你碰到的报错"Value of type 'CartCell' has no member 'navigationController'"其实很好理解:navigationController是UIViewController的专属属性,UITableViewCell本身并没有这个成员,所以直接在Cell类里调用肯定会触发错误。
可行解决方案
我们需要把返回上页的操作交给持有导航控制器的ViewController来处理,这里给你推荐几种贴合iOS开发最佳实践的方案:
方案1:扩展闭包回调(适配你现有代码结构)
你已经在使用updatePrice闭包做价格更新,那可以直接扩展闭包的职责,或者新增一个专门的回调来通知ViewController执行返回:
- 先在
CartCell类里新增一个返回操作的闭包属性:
class CartCell: UITableViewCell { // 保留原有价格更新闭包 var updatePrice: ((Bool) -> Void)? // 新增返回上页的回调闭包 var triggerPopAction: (() -> Void)? // ... 你的其他已有代码 }
- 修改CartCell删除方法里的返回逻辑,替换原来的
navigationController调用:
self.updatePrice = { [weak self] isUpdate in guard let self = self else { return } if arrayGlobleCart.count == 0 { // 触发闭包,把返回操作交给ViewController处理 self.triggerPopAction?() } }
- 在创建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的事件,代理模式会让代码结构更清晰:
- 定义一个代理协议:
protocol CartCellDelegate: AnyObject { func cartCellDidNeedPop(_ cell: CartCell) }
- 在CartCell中添加代理属性:
class CartCell: UITableViewCell { weak var delegate: CartCellDelegate? // ... 其他代码 }
- 在删除方法中调用代理方法:
self.updatePrice = { [weak self] isUpdate in guard let self = self else { return } if arrayGlobleCart.count == 0 { self.delegate?.cartCellDidNeedPop(self) } }
- 在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
相关产品推荐
相关产品推荐

