macOS Swift多窗口应用:指定ViewController通知与焦点窗口识别问题
macOS多窗口AppKit问题解决方案
一、精准通知特定ViewController
1. 直接引用调用(推荐)
放弃全局通知,直接获取目标ViewController实例调用对应方法:
- 在AppDelegate中维护窗口与ViewController的映射表,窗口创建时添加关联,关闭时移除:
// AppDelegate 代码 var windowVCMap = [NSWindow: ViewController]() // 窗口初始化完成后调用 func registerWindowVC(window: NSWindow, vc: ViewController) { windowVCMap[window] = vc } // 需要通知特定VC时 if let targetVC = windowVCMap[targetWindow] { targetVC.handleTargetEvent(extraData: someData) // 直接调用VC的业务方法 }
2. 带对象的通知发送
若必须使用通知机制,发送时指定object为目标VC实例,监听时限定接收该object的通知:
- 发送通知:
NotificationCenter.default.post( name: .customTargetNotification, object: targetViewController, // 指定目标VC为通知关联对象 userInfo: ["payload": data] )
- 监听通知(在ViewController内部):
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(handleCustomNotification(_:)), name: .customTargetNotification, object: self // 仅接收以当前VC为object的通知 ) }
二、正确识别获得焦点的ViewController
1. 绑定窗口监听激活事件
每个ViewController只监听自身所属窗口的didBecomeKeyNotification:
override func viewDidLoad() { super.viewDidLoad() guard let currentWindow = view.window else { return } NotificationCenter.default.addObserver( self, selector: #selector(onWindowBecameKey(_:)), name: NSWindow.didBecomeKeyNotification, object: currentWindow // 仅监听自己窗口的激活事件 ) }
2. 主动获取当前活跃VC
通过系统API直接拿到当前焦点窗口对应的ViewController:
if let keyWindow = NSApplication.shared.keyWindow, let activeVC = keyWindow.contentViewController as? ViewController { // 处理活跃VC的业务逻辑 }
注意事项
- 务必在ViewController销毁时移除通知监听,避免内存问题:
deinit { NotificationCenter.default.removeObserver(self) }
内容的提问来源于stack exchange,提问作者user29306905
相关产品推荐
相关产品推荐

