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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:40:21