windowShouldClose return 错误,但 window 关闭

windowShouldClose return false, but window closed

当用户点击 NSWindow 左上角的红色 x 时,我需要在后台做一些事情,

NSWindowDelegate 方法 windowShouldClose(_:) return false,但 window 关闭。并且 GCD 闭包从不调用。

控制台日志是 1 - 2 - 3 - 5 - 7,我希望它是 1 - 2 - 3 - 5 - 4 - 7。

代码有什么问题?

编辑: 在脸上,我希望 window 在用户单击红色 x 时隐藏,我会做一些背景,然后在 1 秒后关闭 window。

class ViewController: NSViewController, NSWindowDelegate {

    override func viewWillAppear() {
        super.viewWillAppear()
        view.window?.delegate = self
    }

    func windowShouldClose(_ sender: NSWindow) -> Bool {
        print("1")
        if sender.isVisible {
            print("2")
            sender.orderOut(nil)
            // do something here
            print("3")
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                print("4")
                sender.close()
            }
            print("5")
            return false
        } else {
            print("6")
            return true
        }
    }

    func windowWillClose(_ notification: Notification) {
        print("7")
    }

}

最后:

1 - 2 - 3 - 5 - 4 - 7


class ViewController: NSViewController, NSWindowDelegate {

    override func viewWillAppear() {
        super.viewWillAppear()
        view.window?.delegate = self
    }

    func windowShouldClose(_ sender: NSWindow) -> Bool {
        print("1")
        if sender.isVisible {
            print("2")
            sender.orderBack(nil)
            // do something here
            print("3")
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                print("4")
                sender.close()
            }
            print("5")
            return false
        } else {
            print("6")
            return true
        }
    }

    func windowWillClose(_ notification: Notification) {
        print("7")
    }

}

感谢 Malik 和 Parag Bafna。

这里摘录自Apple docs

The close method posts an willCloseNotification notification to the default notification center.

The close method differs in two important ways from the performClose(_:) method:

  • It does not attempt to send a windowShouldClose(_:) message to the window or its delegate.

  • It does not simulate the user clicking the close button by momentarily highlighting the button.

Use performClose(_:) if you need these features.

鉴于上述情况,请尝试将您的代码更新为如下内容

class ViewController: NSViewController, NSWindowDelegate {

    override func viewWillAppear() {
        super.viewWillAppear()
        view.window?.delegate = self
    }

    func windowShouldClose(_ sender: NSWindow) -> Bool {
        print("1")
        if sender.isVisible {
            print("2")
            sender.orderOut(nil)
            // do something here
            print("3")
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                print("4")
                sender.performClose(nil) //THIS IS THE KEY
            }
            print("5")
            return false
        } else {
            print("6")
            return true
        }
    }

    func windowWillClose(_ notification: Notification) {
        print("7")
    }

}

orderOut 内部调用 windowShouldClose 造成了问题。
使用 orderBackisKeyWindow 检查

func windowShouldClose(_ sender: NSWindow) -> Bool {
    print("1")
    if sender.isKeyWindow {
        print("2")
        sender.orderBack(nil)

        // do something here
        print("3")
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            print("4")
            sender.performClose(nil)
        }
        print("5")
        return false
    } else {
        print("6")
        return true
    }
}

或 return 错误来自 applicationShouldTerminateAfterLastWindowClosed