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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:24:59