applicationWillTerminate not being called

macOS 10.14.6 (Mojave)

Xcode 11.2.1 (11B500)

Language: Objective-C


An out of the box macOS application does not call the delgate applicationWillTerminate.


I have logs in both applicationDidFinishLaunching and applicationWillTerminate in the default source.


- (void)applicationDidFinishLaunching:(NSNotification *)notification {

    NSLog(@"applicationDidFinishLaunching");
}

- (void)applicationWillTerminate:(NSNotification *)notification {

    NSLog(@"applicationWillTerminate");
}


applicationDidFinishLaunching logs fine; but applicationWillTerminate does not get executed at all while quiting. Again this is a default app generation for macOS (No options/Objective-C).


Known issue? Bug?


Thanks,


Neil

Accepted Reply

`Xcode 11 seems to be including `Application can be killed immediately when user is shutting down or logging out` in apps' Info.plist with a value of YES, which will result in what you see. Set it to NO, or remove it.

Replies

Does applicationDidEnterBackground get called?

When restarting does applicationWillEnterForeground get called or does application:didFinishLaunchingWithOptions get called?

Why do you think your app 'terminates'?


Are you familiar with:

https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle?language=objc

Thanks PBK, As per my post; this is a macOS application (not iOS). Yes, the default generated App terminates and UIKit is not a factor. Unfortunately, applicationWillTerminate never gets called so we can correctly clean up server connections and whatnot.


Again, I created a brand new "out of the box" application to confirm. In both Objective-C (and Swift); applicationWillTerminate is not called. NSLog and Breakpoints applied. applicationDidFinishLaunching gets executed.


Regards,


Neil

I observed the same in a Swift project, with some strange behavior.

Conf: OSX 10.14.6 - XCode 11.2 ß2 - Swift


I created an empty OSX project, just adding a print in willTerminate

    func applicationWillTerminate(_ aNotification: Notification) {
        print("Will terminate")
    }



When I quit the app, nothing printed.


I added a WKWebView in the main window, with the following code in the ViewController:

import Cocoa
import WebKit

class ViewController: NSViewController {

    @IBOutlet weak var webView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let url = URL(string: "https://www.apple.com")
        let request = URLRequest(url:url!)
        webView.load(request)
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

}

I set the entitlements for out connections and ran


I got the log printed.


I started again, making incremental changes from the empty project

never printed until I loaded the request.


I commented out

     //   webView.load(request)


No more print.


Cannot figure out what is going on here.


Bug report filed: Nov 30, 2019 at 5:37 PM – FB7473098


EDITED:

Tested as well with ObjC: willTerminate does not print log on an "empty" app.

`Xcode 11 seems to be including `Application can be killed immediately when user is shutting down or logging out` in apps' Info.plist with a value of YES, which will result in what you see. Set it to NO, or remove it.

In my case, this is set to YES and there's no crash. As well as under special circumstances.

With XCode 11.2ß2 and XCode 11.2.1


"Application can be killed to reclaim memory or other exceptional circumstances

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<true/>

</plist>


Application can be killed immediately when user is shutting down or logging out

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<true/>

</plist>


But that may behave different on mvannote Mac ?

Yep, that did the trick, thanks for that. BUT "Application can be killed immediately when user is shutting down or logging out" does not apply in my case. All I am doing is quiting the app, NOT "shutting down or logging out"; This is obviously a huge bug and should not be the default for macOS.


Regards,


Neil

There may be some other root cause.


In my case, those properties were set to YES and I did not get any crash.


Did you file a bug ?

Well, In my original post, there wasn't a "crash" but just a straight out applicationWillTerminate not getting called at all without notice. This method being called (when expected) is really kind of important for applications that may have uncommitted resources hanging out in the breeze.


The verbiage "Application can be killed immediately when user is shutting down or logging out" seems to indicate when the user is shutting down or logging out of the machine/account; Not just normally quitting an application.


Bug will be filed in the next day or two.


- Neil

This problem also occurs if just hitting quit in the app...


Whats the f_+++ purpose of such a method call if it aint being called.


And to Apple, please exclude those calls from your templates if you add those weird .plist entries.


This confuses ANYONE especially newbies who wont be able to figure out why that method which you put in there in the template isnet bein called, even though your docs. state it will be...


This is another glitch happening due to your tempo of putting out new macOS's ... Quality is severly degrading !

You aren't going to have much luck with Apple. I can reproduce this problem on a new project. I may have already discovered it and forgotten about it. This seems familiar.


If necessary, you can re-direct the quit command in the menubar to a "quit:" action in your app delegate. Do your clean up there and then send terminate: to the shared application object.


But ideally, you want to design your app so that it doesn't need any cleaning up. Users can force quit your app at any time.


And I wouldn't necessarily consider this to be a "glitch". This is the way iOS apps work. Hint, Hint. Maybe you should ensure that your Mac apps work well in a more iOS-like environment. Hint, Hint.


PS: If you have ever build a document-based app, this idea should not be surprising. NSDocument classes are never destroyed or deallocated. If you have a document-based app and you have resourced that need to be cleaned up in dealloc, you need to make sure to perform your cleanup in "windowWillClose:", set all pointers to nil, and then do the same cleanup in dealloc just to be safe.

Well, I do agree with Introspectr in cosidering this bug a "glitch". I personally don't understand why we should downgrade features and behavior of macOS apps just to fit portable devices (iOS in this case).

Actually I've discovered that "applicationShouldTerminate" is not called either (macOS env obviously), which prevent me to garcefully stop, for example, some lengthy task or ask for user's confirmation, instead of abruply stop everything.

Hence, in my opinion it is a serious bug, at least from the perspective of the template code set up by Apple itself.

having same issue, need to do some cleanup when mac app is closed, saw this hint on a stack overflow post

https://stackoverflow.com/questions/8193305/applicationwillterminate-not-called

add this function to the mac app delegate, and then the applicationWillTerminate: method is called

-(BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender{
return YES;
}

i havent tested all cases e.g. user kills an app with kill -9 or something like that, i just checked the window close case at this point

(you may need to set both of the aforementioned info plist values in the other chat responses here to NO. I have them set to NO. i did not go thru testing iterations with those plist values. one or both may not be needed.) see attached screenshot for plist settings i used.

Update: If you use normal quit from Activity Monitor, this solution traps the exit. If you use force quit, it does not (which kind of makes sense). (That may be the kill -9).

also, an app crash doesnt seem to trigger the WillTerminate

test:

// at end of did finish launching:
       [self performSelector:@selector(forceCrash) withObject:nil afterDelay:10];

-(void)forceCrash {

  int *x = NULL;
  int y = *x;

}

so, at least normal app close is handled