【问题标题】:NSWindow not closing when created with custom NSApplication使用自定义 NSApplication 创建时 NSWindow 未关闭
【发布时间】:2016-07-07 18:00:56
【问题描述】:

我正在创建自己的 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 时会溢出。

问题是,当我点击红色的关闭按钮时,窗口没有关闭,当我从停靠图标菜单中选择“退出”时,它没有退出。为什么会这样?

编辑:this answer.中讨论了同样的问题

编辑 2:我创建了这段代码的 Objective-c 版本,一切正常。我怀疑问题是我不能在 Swift 中使用 NSAnyEventMask。

【问题讨论】:

    标签: swift cocoa nswindow


    【解决方案1】:

    您应该只在self.running 时重复。这可以解释为什么您的应用程序不会退出。如果您的应用程序配置为在其最后一个窗口关闭时退出,它也可以解释您的窗口没有关闭的原因。无论如何,如果整个应用程序要退出,框架可能不会费心单独关闭窗口。

    【讨论】:

    • 问题是,它所做的并不是让它运行。我无法在不调用 super.run() 的情况下明确设置 running
    • 嗯。是的,我看到 Apple 的旧 GLUT sample code 采用直接设置超类的 _running 实例变量的方式,而 Swift 可能不允许这样做。所以,你可以尝试使用 KVC 来做到这一点:setValue(true, forKey:"running").
    • 老实说,我以前从未听说过,你能把它放到代码示例中吗?粘贴你放的东西是行不通的。 ——不管我说什么,但它不起作用。
    【解决方案2】:

    我似乎已经解决了这个问题,在 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()
        }
    } 
    

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      相关资源
      最近更新 更多