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

macOS Cocoa应用调用NSApp.activate()后无法激活并获取焦点的问题求助

macOS Cocoa应用调用NSApp.activate()后无法激活并获取焦点的问题求助

我最近做了个简单的Cocoa小应用,需求是通过键盘快捷键把应用窗口调到前台并让它获取焦点,但折腾了好久都没搞定,想请教下大家怎么解决。

先贴下我的代码:

import Cocoa
import HotKey

class ViewController: NSViewController {
    let hotKey = HotKey(key: .s, modifiers: .option)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        hotKey.keyUpHandler = {
            self.show()
        }
    }
    
    @objc func show(){
        NSApp.activate()
        view.window?.orderFrontRegardless()
        DispatchQueue.main.async {
            self.view.window?.makeKey()
        }
    }
}

class CustomWindow: NSWindow {
    override var canBecomeKey: Bool { true }
    override var canBecomeMain: Bool { true }
}

我用Option + S这个快捷键测试,现在的问题是:按快捷键确实能把应用窗口带到前台,但窗口并没有真正获取焦点——标题栏不是激活状态的高亮样式,macOS顶部菜单栏还停留在之前活跃的应用上,只有我手动点击窗口标题栏或者窗口内容区域,应用才会真正激活,菜单栏也切换过来。

我本来以为下面这段代码能同时激活应用并让窗口获取焦点,但完全没用:

NSApp.activate()
view.window?.orderFrontRegardless()
DispatchQueue.main.async {
    self.view.window?.makeKey()
}

后来我还尝试了这些办法,都没解决:

  • 子类化NSWindow(就是上面的CustomWindow),把canBecomeKey和canBecomeMain都设为true,并且在Storyboard里把窗口指定为这个子类,结果没有任何变化
  • 修改show()方法成下面这样,结果连窗口都调不到前台了:
@objc func show(){
    print("show: \(view.window)")
    NSApp.activate(ignoringOtherApps: true)
    view.window?.makeKeyAndOrderFront(nil)
}
  • 加了300ms的延迟再调用窗口激活方法,打印window.isKeyWindow始终返回false:
@objc func show(){
    print("show")
    NSApp.activate(ignoringOtherApps: true)
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
        guard let window = self.view.window else { return }
        window.makeKeyAndOrderFront(window)
        print("window: \(window.isKeyWindow)") // 这里一直打印false
    }
}

我的系统是macOS Sequoia 15.5,有没有遇到过类似问题的朋友,能告诉我怎么才能让快捷键触发后,应用窗口自动获取焦点、菜单栏也切换过来吗?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:20:29