Swift中如何强制激活菜单栏应用的About窗口?
问题
我开发了一个菜单栏应用,已将“Application is background only”设置为true。在AppDelegate中编写了创建About窗口的函数,但无法强制该窗口成为当前活动窗口并获取焦点。
点击About按钮打开窗口后,窗口无法激活,点击窗口本身也不会使其激活,点击桌面等外部区域也不会让它失活;只有多次点击About按钮后,窗口才会激活。
希望实现类似“About This Mac”窗口的效果:窗口显示后自动成为活动窗口,点击外部区域时失活,再次点击窗口时重新激活。
相关代码如下:
@main struct MenuBarApp: App { @NSApplicationDelegateAdaptor var appDelegate: AppDelegate @StateObject var appState: AppState = AppState.shared var body: some Scene { MenuBarExtra("MenuBarApp", systemImage: "rectangle.and.text.magnifyingglass") { ContentView() .environmentObject(appState) .environmentObject(appDelegate) }.menuBarExtraStyle(.window) } }
private var aboutWindowController: NSWindowController? func showAboutWindow() { if aboutWindowController == nil { let window: NSWindow = NSWindow( contentRect: NSRect.zero, styleMask: [.closable, .titled, .fullSizeContentView], backing: .buffered, defer: false ) window.title = "About Window" window.contentView = NSHostingView(rootView: AboutView()) window.titlebarAppearsTransparent = true window.center() window.makeKeyAndOrderFront(self) aboutWindowController = NSWindowController(window: window) } aboutWindowController?.showWindow(aboutWindowController?.window) }
解决方案
要实现目标效果,需针对后台应用的窗口激活规则做以下调整:
- 修改窗口激活属性:后台应用的窗口默认无法成为关键或主窗口,需显式设置
canBecomeKey = true和canBecomeMain = true。 - 主动激活应用:在显示窗口前调用
NSApp.activate(ignoringOtherApps: true),强制激活应用,确保窗口能获取焦点。 - 调整窗口显示逻辑:先通过窗口控制器管理窗口,再调用
makeKeyAndOrderFront,避免顺序错误导致的激活失败。
修改后的showAboutWindow函数代码:
private var aboutWindowController: NSWindowController? func showAboutWindow() { if aboutWindowController == nil { // 建议设置固定初始尺寸,避免零尺寸窗口的潜在问题 let window: NSWindow = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 400, height: 300), styleMask: [.closable, .titled, .fullSizeContentView], backing: .buffered, defer: false ) window.title = "About Window" window.contentView = NSHostingView(rootView: AboutView()) window.titlebarAppearsTransparent = true window.center() // 允许窗口成为关键窗口和主窗口 window.canBecomeKey = true window.canBecomeMain = true aboutWindowController = NSWindowController(window: window) } // 先激活应用,确保后续窗口能获取焦点 NSApp.activate(ignoringOtherApps: true) // 让窗口成为关键窗口并显示 aboutWindowController?.window?.makeKeyAndOrderFront(self) }
额外注意:
- 确认
AboutView的视图层级没有拦截事件,保证窗口能响应点击激活 - 检查
Info.plist中LSUIElement(即“Application is background only”)的设置为YES,确保应用处于后台模式
内容的提问来源于stack exchange,提问作者4c65736975
相关产品推荐
相关产品推荐

