容器视图嵌入时父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
相关产品推荐
相关产品推荐

