从代码创建的TableView Header访问UITableViewController代理实现Segue跳转问题
问题根源
你当前代理无效的核心原因是代理传递的层级错位:delegate4是定义在PendingNotificationsHeader类中的属性,你直接给外层的pendingNotificationCustomCell赋值delegate4自然不会生效,加上你手动初始化的cell和TableView复用的cell不是同一个实例,所以赋值一直为空。
解决方案
按以下步骤调整代码即可去掉单例方案,用代理实现需求:
- 首先给外层自定义cell
pendingNotificationCustomCell新增代理属性,用来承接主控制器的引用:
// 定义代理协议,建议继承AnyObject避免循环引用 protocol PendingCellActionDelegate: AnyObject { func callSegueFromCell2(myData dataobject: AnyObject) } class pendingNotificationCustomCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate { // 新增弱引用代理属性 weak var actionDelegate: PendingCellActionDelegate? // 原有代码保持不变 ... }
- 实现
pendingNotificationCustomCell中PendingTableView的viewForHeaderInSection代理方法,将代理向下传递给Header实例:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { guard let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "pendingHeaderID") as? PendingNotificationsHeader else { return nil } // 把当前cell拿到的主控制器代理传递给Header header.delegate4 = self.actionDelegate return header }
- 调整
PendingNotificationsHeader中的代理属性为弱引用可选型,避免循环引用和隐式解包崩溃:
class PendingNotificationsHeader: UITableViewHeaderFooterView { // 修改为弱引用可选型,不要用隐式解包 weak var delegate4: MyCustomCellDelegator3? // 原有代码保持不变 ... @IBAction func createNewPriceAlertButtonPressed(_ sender: Any) { print ("##### New Price Alert Label Pressed") let myData = self // 现在可以正常调用代理方法 delegate4?.callSegueFromCell2(myData: myData) } }
- 在主
UITableViewController的cellForRowAt方法中,给复用生成的pendingNotificationCustomCell实例赋值代理:
// 主控制器的cellForRowAt方法中 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 对应位置生成pendingNotificationCustomCell的逻辑 guard let cell = tableView.dequeueReusableCell(withIdentifier: "你对应的cell复用ID", for: indexPath) as? pendingNotificationCustomCell else { return UITableViewCell() } // 给cell的代理赋值为主控制器自身 cell.actionDelegate = self // 其他cell赋值逻辑 return cell }
- 最后确保主控制器遵守
MyCustomCellDelegator3协议,实现callSegueFromCell2方法执行segue逻辑即可。
注意事项
- 所有代理属性必须加
weak修饰,避免出现循环引用导致内存泄漏 - 不要手动初始化cell给代理赋值,TableView会复用cell,必须在
cellForRowAt中给复用出来的真实cell实例赋值才会生效
内容的提问来源于stack exchange,提问作者PJS
相关产品推荐
相关产品推荐

