Search code examples
swiftcocoagrand-central-dispatchnswindow

windowShouldClose return false, but window closed


i need do something in background when user click the red x at upper left of NSWindow,

NSWindowDelegate method windowShouldClose(_:) return false, but the window close. and the GCD closure never call.

the console log is 1 - 2 - 3 - 5 - 7, and i want it be 1 - 2 - 3 - 5 - 4 - 7.

what's the problem of the code?

EDIT: In face, i want window just hidden when user click red x, and i will do something background, and then close window after 1 second.

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")
    }

}

Finally:

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")
    }

}

Thanks for Malik and Parag Bafna.


Solution

  • orderOut call inside windowShouldClose is creating the issue.
    Use orderBack and isKeyWindow check

    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
        }
    }
    

    or return false from applicationShouldTerminateAfterLastWindowClosed