使用自定义 NSApplication 创建时 NSWindow 不关闭
NSWindow not closing when created with custom NSApplication
我正在创建自己的 NSApplication 子类,运行 遇到了障碍。这是我对 run()
方法的实现。
override func run() {
finishLaunching()
repeat {
let event = nextEventMatchingMask(0xfffffffffffffff, untilDate: NSDate.distantPast(), inMode: NSDefaultRunLoopMode, dequeue: true)
if event != nil { sendEvent(event!) }
updateWindows()
} while true
}
在我的 main.swift
我有这个:
let myApp: MyApplication = MyApplication.sharedApplication() as! MyApplication
let window = NSWindow(contentRect: NSMakeRect(0, 0, 100, 100), styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask , backing: .Buffered, defer: false)
window.makeKeyAndOrderFront(nil)
myApp.run()
之所以使用0xfffffffffffffff
而不是Int(NSEventMask.AnyEventMask.rawValue)
是因为后者在从UInt64
转换为Int
时会溢出。
问题是,当我点击红色关闭按钮时,window 没有关闭,当我从停靠图标菜单中 select "Quit" 时,它没有放弃。为什么会这样?
编辑:this answer.
中讨论了同样的问题
编辑 2:我创建了此代码的 objective-c 版本,一切正常。我怀疑问题是我无法在 Swift.
中使用 NSAnyEventMask
您应该只在 self.running
时重复。这可以解释为什么您的应用程序没有退出。如果您的应用配置为在其最后一个 window 关闭时退出,它也可以解释为什么您的 window 没有关闭。无论如何,如果整个应用程序要退出,框架可能不会费心单独关闭 window。
我似乎已经解决了问题,在Objective-C中我可以只使用它,我的应用程序将响应停靠菜单中的退出项。
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue:YES];
在 Swift 中,如果您尝试像这样获取下一个事件,您会这样做:
let event = nextEventMatchingMask(Int(NSEventMask.AnyEventMask.rawValue),
untilDate: NSDate.distantPast(),
inMode: NSDefaultRunLoopMode,
dequeue: true)
但是,从 UInt64 转换为 Int 时出现溢出错误。这似乎是无意的。起初,我试图通过将其替换为 0xfffffffffffffff
来解决此问题。这工作正常,应用程序会响应事件。但实际上这还不够。该应用还需要响应与掩码 0x1
匹配的事件。我不知道为什么,但这让我可以退出并从停靠栏菜单中隐藏我的应用程序。 (0x0
只允许我退出。)
那么,Swift NSApplication 子类的整个 run()
实现是这样的:
override func run() {
finishLaunching()
setValue(true, forKey: "running")
while true {
let event = nextEventMatchingMask(0xfffffffffffffff, untilDate: NSDate.distantPast(), inMode: NSDefaultRunLoopMode, dequeue: true)
let dockEvent = nextEventMatchingMask(0x1, untilDate: NSDate.distantPast(), inMode: NSDefaultRunLoopMode, dequeue: true)
if dockEvent != nil { sendEvent(dockEvent!) }
if event != nil { sendEvent(event!) }
if !running { break }
updateWindows()
}
}
我正在创建自己的 NSApplication 子类,运行 遇到了障碍。这是我对 run()
方法的实现。
override func run() {
finishLaunching()
repeat {
let event = nextEventMatchingMask(0xfffffffffffffff, untilDate: NSDate.distantPast(), inMode: NSDefaultRunLoopMode, dequeue: true)
if event != nil { sendEvent(event!) }
updateWindows()
} while true
}
在我的 main.swift
我有这个:
let myApp: MyApplication = MyApplication.sharedApplication() as! MyApplication
let window = NSWindow(contentRect: NSMakeRect(0, 0, 100, 100), styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask , backing: .Buffered, defer: false)
window.makeKeyAndOrderFront(nil)
myApp.run()
之所以使用0xfffffffffffffff
而不是Int(NSEventMask.AnyEventMask.rawValue)
是因为后者在从UInt64
转换为Int
时会溢出。
问题是,当我点击红色关闭按钮时,window 没有关闭,当我从停靠图标菜单中 select "Quit" 时,它没有放弃。为什么会这样?
编辑:this answer.
中讨论了同样的问题编辑 2:我创建了此代码的 objective-c 版本,一切正常。我怀疑问题是我无法在 Swift.
中使用 NSAnyEventMask您应该只在 self.running
时重复。这可以解释为什么您的应用程序没有退出。如果您的应用配置为在其最后一个 window 关闭时退出,它也可以解释为什么您的 window 没有关闭。无论如何,如果整个应用程序要退出,框架可能不会费心单独关闭 window。
我似乎已经解决了问题,在Objective-C中我可以只使用它,我的应用程序将响应停靠菜单中的退出项。
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue:YES];
在 Swift 中,如果您尝试像这样获取下一个事件,您会这样做:
let event = nextEventMatchingMask(Int(NSEventMask.AnyEventMask.rawValue),
untilDate: NSDate.distantPast(),
inMode: NSDefaultRunLoopMode,
dequeue: true)
但是,从 UInt64 转换为 Int 时出现溢出错误。这似乎是无意的。起初,我试图通过将其替换为 0xfffffffffffffff
来解决此问题。这工作正常,应用程序会响应事件。但实际上这还不够。该应用还需要响应与掩码 0x1
匹配的事件。我不知道为什么,但这让我可以退出并从停靠栏菜单中隐藏我的应用程序。 (0x0
只允许我退出。)
那么,Swift NSApplication 子类的整个 run()
实现是这样的:
override func run() {
finishLaunching()
setValue(true, forKey: "running")
while true {
let event = nextEventMatchingMask(0xfffffffffffffff, untilDate: NSDate.distantPast(), inMode: NSDefaultRunLoopMode, dequeue: true)
let dockEvent = nextEventMatchingMask(0x1, untilDate: NSDate.distantPast(), inMode: NSDefaultRunLoopMode, dequeue: true)
if dockEvent != nil { sendEvent(dockEvent!) }
if event != nil { sendEvent(event!) }
if !running { break }
updateWindows()
}
}