16

How to handle close event of the window using swift, for example, to ask "Are you sure you want to close the form?"

enter image description here

The form will be closed in the case "yes" and not closed in the case "no". Showing message box is not a problem for me.

viewWillDisappear() works for minimizing also, but I need only close event.

Thanks.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Evgeniy
  • 403
  • 1
  • 8
  • 18

4 Answers4

19

Like said above, you should make the ViewController an NSWindowDelegate, but you should handle windowWillClose, not windowShouldClose. windowShouldClose is to determine if the window is able to close or not, not an event that the window is actually closing.

I also found that you need to set up the delegate in viewDidAppear, not viewDidLoad. For me self.view.window wasn't defined yet in viewDidLoad.

override func viewDidAppear() {
    self.view.window?.delegate = self
}
Shmidt
  • 16,436
  • 18
  • 88
  • 136
Thomas Alvarez
  • 266
  • 1
  • 4
  • what does self.view.window?.delegate = self do exactly plz? – Nabeel Khan Dec 24 '16 at 20:57
  • 2
    Sets the ViewController to be a delegate for the Window that the ViewController represents. It allows the ViewController that is conforming to the NSWindowDelegate protocol to actually function as a delegate. – Thomas Alvarez Dec 25 '16 at 23:26
11

I was having the same query too, solved it using the method explained in detail here: Quit Cocoa App when Window Close using XCode Swift 3

It needs three steps:

  1. Conform toNSWindowDelegate in your ViewController class
  2. Override viewDidAppear method
  3. Add windowShouldClose method

The added code should look like this:

class ViewController: NSViewController, NSWindowDelegate {
    // ... rest of the code goes here
    override func viewDidAppear() {
        self.view.window?.delegate = self
    }
    func windowShouldClose(_ sender: Any) {
        NSApplication.shared().terminate(self)
    }
}
Nabeel Khan
  • 3,715
  • 2
  • 24
  • 37
  • 7
    windowShouldClose is a delegate method that returns a boolean value to determine if the window should be allowed to close or not. You should be using windowWillClose. You also don't need to manually terminate the application in code. There is an NSApplicationDelegate method you can put in your AppDelegate to have the app close when all windows are closed. func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } – Thomas Alvarez Dec 25 '16 at 23:30
3

You can use the NSWindowDelegate protocol in your ViewController class. (See the documentation here)

To make your class conform to the protocol:

class ViewController: NSObject, NSWindowDelegate

To detect when the window's close button has been clicked, use windowShouldClose:

From the doc:

Tells the delegate that the user has attempted to close a window [...]

In this method, you can use NSAlert to prompt the user on whether or not they really want to close the window.

EDIT (in response to @Mr Beardsley's comment)

To make your ViewController the delegate, use:

window.delegate = self

Where self is the ViewController and window is the window you're using. You can put this in viewDidLoad:.

Arc676
  • 4,445
  • 3
  • 28
  • 44
  • Thanks for the answer. I set "class ViewController: NSObject, NSWindowDelegate" and realized function windowShouldClose. But it doesn't work. I believe I should set the delegate property for the window but I don't know how. – Evgeniy Oct 19 '15 at 14:58
  • 2
    To set the delegate from your View Controller just do something like: "window.delegate = self" In viewDidLoad (as long as you are on 10.10 or later). You will need a reference or IBOutlet to the window in question as well. – Mr Beardsley Oct 19 '15 at 15:18
3

Just add this function to AppDelegate ...

func applicationShouldTerminateAfterLastWindowClosed (_ theApplication: NSApplication) -> Bool {
    return true
}
Tourelou
  • 31
  • 1