【发布时间】:2020-08-26 12:01:43
【问题描述】:
我有一个只有NSStatusItem 的小型应用程序,带有一个设置窗口。从NSStatusItem 的菜单中,我想重新激活主窗口。
应用程序保留一个 NSWindow 实例,该实例设置为在关闭时不释放。
关闭窗口后,我将应用程序的激活策略更改为accessory,因此 Dock 图标对用户隐藏。
当用户重新打开窗口时,我将激活策略改回regular并再次显示窗口。
这是隔离问题的示例应用中我的应用委托的全部内容:
import Cocoa
import SwiftUI
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
var statusItem: NSStatusItem!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Create the window and set the content view.
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: EmptyView())
window.makeKeyAndOrderFront(nil)
window.isReleasedWhenClosed = false
window.delegate = self
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
statusItem.button?.title = "X"
statusItem.button?.target = self
statusItem.button?.action = #selector(toggleWindow(sender:))
NSApp.setActivationPolicy(.accessory)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
@objc func toggleWindow(sender: AnyObject) {
if window.isVisible {
window.close()
} else {
window.makeKeyAndOrderFront(nil)
NSApp.activate(ignoringOtherApps: true)
NSApp.setActivationPolicy(.regular)
}
}
}
extension AppDelegate: NSWindowDelegate {
func windowWillClose(_ notification: Notification) {
NSApp.setActivationPolicy(.accessory)
}
}
该应用是 Xcode 11 的默认模板,但我将主视图更改为 EmptyView(),因此不需要额外的类。
如果我用信号量按钮关闭窗口,然后用状态栏图标重新打开它,它工作正常。
但是,如果我通过 CMD-W 关闭它并重新打开它,我会返回窗口,但菜单仍然处于选中状态,就好像之前的关闭命令没有完成一样。
由于菜单处于这种奇怪的状态,应用程序不会响应事件,直到菜单问题得到解决(例如,通过单击另一个菜单项)。
更新:
作为一种解决方法,我发现如果我在几毫秒后更改激活策略,菜单问题就解决了:
func windowWillClose(_ notification: Notification) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
NSApp.setActivationPolicy(.accessory)
}
}
但是,一旦窗口出现,它仍然不能正确处理事件(错过了第一次点击)。
【问题讨论】: