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

容器视图嵌入时父VC代理方法未触发,如何让父子VC代理均响应?

嘿,这个问题我之前也碰到过!核心原因是你的BLEManager里的delegate是单个弱引用变量——当HomeVC先把自己设为代理后,ChildVC在它的viewWillAppear里又把自己赋值给了同一个delegate,直接覆盖了之前的设置,所以只有最后赋值的那个VC(也就是ChildVC)的代理方法会被触发。

要让两个VC都能响应代理方法,咱们需要把单个代理改成多代理数组,同时还要用弱引用存储这些代理对象,避免循环引用。下面是具体的修改方案:

1. 保持协议不变

你的BLEManagerDelegate协议没问题,继续用就行:

public protocol BLEManagerDelegate: class {
    func bLEManagerShowAlert(message: String)
}

2. 重构BLEManager实现多代理

把原来的单个delegate替换成弱引用数组,同时添加添加/移除代理的方法,最后在触发事件时遍历所有代理调用方法:

public class BLEManager: NSObject {
    static let sharedInstance = BLEManager()
    
    // 用NSHashTable存储弱引用代理,自动管理已销毁的对象
    private var delegates = NSHashTable<BLEManagerDelegate>.weakObjects()
    
    // 添加代理
    public func addDelegate(_ delegate: BLEManagerDelegate) {
        delegates.add(delegate)
    }
    
    // 移除代理(VC销毁时调用,避免不必要的回调)
    public func removeDelegate(_ delegate: BLEManagerDelegate) {
        delegates.remove(delegate)
    }
    
    public func postMessage(message: String) {
        // 遍历所有存活的代理,调用方法
        for delegate in delegates.allObjects {
            delegate.bLEManagerShowAlert(message: message)
        }
    }
}

这里用NSHashTable<BLEManagerDelegate>.weakObjects()是因为它会自动处理弱引用的对象,当某个VC被销毁时,会自动从数组中移除,不会产生野指针问题。

3. 修改HomeVC和ChildVC的代理设置

不再直接赋值delegate,而是调用addDelegate方法,同时在viewWillDisappear里移除代理(推荐这么做,避免VC销毁后还收到回调):

HomeVC的修改:

class HomeVC: ContentViewController, BLEManagerDelegate {
    let bLEManager = BLEManager.sharedInstance
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        bLEManager.addDelegate(self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        bLEManager.removeDelegate(self)
    }
    
    func bLEManagerShowAlert(message: String) {
        // 现在这个方法会被正常触发啦
        print("HomeVC收到BLE消息:\(message)")
    }
}

ChildVC的修改:

class ChildVC: UITableViewController, BLEManagerDelegate {
    let bLEManager = BLEManager.sharedInstance
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        bLEManager.addDelegate(self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        bLEManager.removeDelegate(self)
    }
    
    func bLEManagerShowAlert(message: String) {
        print("ChildVC收到BLE消息:\(message)")
    }
}

额外提醒

  • 别忘了调用super.viewWillAppear和super.viewWillDisappear,确保父类的生命周期方法正常执行。
  • addDelegate和removeDelegate最好成对调用,避免同一个VC被多次添加到代理数组,导致代理方法被多次触发。
  • NSHashTable的allObjects只会返回当前存活的代理对象,已经被销毁的VC会自动被过滤掉,不用担心崩溃问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:33:42