66

Hi I have read several questions on SO about applicationWillTerminate getting called and not getting called.

I wanted to summarize what I understood as there are several posts that speak differently.

  1. For IOS (without multitasking) it is called always when home button is pressed.

  2. For IOS 4 and above

    a. it is not called when pressing home button (as the app moves to background)

    b. it is called when closing the app from the multi tasking dock and if the app has a sudden terminate flag in info.plist disabled else it is not called. ( I set the "Application should get App Died events" and even then on closing the app from the multitasking dock the terminate function did not get called)

Based on that I had a couple of questions

Is it a good practise to set the Application should get App Died events flag? ( I set the "Application should get App Died events" and even then on closing the app from the multitasking dock the terminate function did not get called)

or

Is registering for "UIApplicationWillTerminateNotification" a better thing to do than the info.plist setting?

Basically I need to do some work only when the app terminates and NOT when it moves to background.

or

EDIT (1): When the app is terminated the following is sent to the APP. How do I catch it?

Program received signal: “SIGKILL”.

EDIT (2):

Please note : It is not getting called in IOS 4 and above when removing from the multitasking dock. You might think it is. But in my case it is not.

I am asking if anyone knows why? Is there something else I am missing.

Also Note I set the "Application should get App Died events" and even then it is not getting called.

EDIT (3):

The answer for the following question also did not work. applicationWillTerminate does not get invoked

Anybody facing the similar issue as me?

Community
  • 1
  • 1
Anand
  • 4,182
  • 6
  • 42
  • 54
  • I have the same problem. One remark: you could not catch SIGKILL, this signal is handled by the OS and is equivalent with removing all the app resources (so no way for your app to catch this signal). – alinoz Oct 19 '11 at 08:14
  • thanks for that. So we are back to finding how to make "applicationWillTerminate" in IOS 4 and above. – Anand Oct 19 '11 at 08:20

7 Answers7

50

In short, unless you have UIApplicationExitsOnSuspend in your Info.plist set to YES, in iOS4 and above there is no guarantee that applicationWillTerminate: will ever get called.

As the documentation says:

For applications that support background execution, this method is generally not called when the user quits the application because the application simply moves to the background in that case. However, this method may be called in situations where the application is running in the background (not suspended) and the system needs to terminate it for some reason

(Emphasis mine.)

If you need to do something before the app exits you need to do it in applicationDidEnterBackground:. There is no way to catch SIGKILL.

Stephen Darlington
  • 51,577
  • 12
  • 107
  • 152
  • looks like there is no way to predict if the applicationWillTerminate is called. – alinoz Oct 19 '11 at 09:16
  • 1
    the doc says that.. but then the function doesn't get called when i close it from the multitasking dock! btw i am running audio in the background, and updating the server with some info when the audio is stopped by the user or when the app is closed. that is why i cannot use applicationDidEnterBackground: – Anand Oct 19 '11 at 09:29
  • Where does it say that it gets called when you close it from the multi-tasking dock? It says the exact _opposite_. It says that it is generally _not_ called. – Stephen Darlington Oct 19 '11 at 09:37
  • I interpreted the 'may' the other way.. fair enough. I guess then I won't be able to do the house cleaning functions I intended to do. This is kind of odd isn't it? – Anand Oct 19 '11 at 12:21
  • Thanks for pointing out "unless you have UIApplicationExitsOnSuspend in your Info.plist set to YES". That is what was terminating my app. Not sure how that setting got put in there, but thanks for pointing it out. – Chuck Krutsinger Jul 13 '17 at 20:56
29

I see -applicationWillTerminate: getting called with the following test. In a new project (I used the 'Single View Application' template), add the following to the AppDelegate:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    NSLog(@"%s", __PRETTY_FUNCTION__);

    __block UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        if (identifier != UIBackgroundTaskInvalid) {
            [[UIApplication sharedApplication] endBackgroundTask:identifier];
            identifier = UIBackgroundTaskInvalid;
        }
    }];

    dispatch_async(dispatch_get_main_queue(), ^{
        for (int i=0; i < 20; i++) {
            NSLog(@"%d", i);
            sleep(1);
        }
        if (identifier != UIBackgroundTaskInvalid) {
            [[UIApplication sharedApplication] endBackgroundTask:identifier];
            identifier = UIBackgroundTaskInvalid;
        }
    });
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

This example will start a background task when the app enters the background. The task is just a 20s delay (with logging once a second) that keeps the app running in the background (note the difference between running in the background and suspended) long enough to allow it to be killed from the app switcher.

So, to test it, run the app, hit the home button to send the app to the background, then before the 20s delay is up, remove the app from the app switcher. After the end of the 20s, -applicationWillTerminate: is called. You can watch the console in Xcode to verify that this is the case.

I tried this in the iOS Simulator for iOS 5.1 and 6.1 (both iPhone) and saw it happen in both cases. I also tested on iPhone 4S running iOS 6.1.2 and saw the same behavior.

Andrew Hershberger
  • 4,152
  • 1
  • 25
  • 35
  • 1
    I also recognize that this is not a definitive description of when `-applicationWillTerminate:` is called, nor is it guaranteed to be comprehensive. Even so, I found it useful to know that it is possible for it to be called even in apps that support background execution. – Andrew Hershberger Feb 27 '13 at 21:33
  • The call to `-applicationWillTerminate:` never happens if you remove the `-applicationDidEnterBackground:` (tested with iOS 7.1). That makes some sense -- an app with a background task running could use the `...willTerminate:` message to end its background task; an app without such tasks doesn't need to do that. – Caleb Apr 22 '14 at 14:18
  • In most cases, -[UIApplication applicationWillTerminate:] will never be called, unless the application is terminated by the iOS system(such as memory not enough). So when crashed or killed by the user, it will not be called. – DawnSong Apr 22 '15 at 02:24
  • 4
    If you directly double click on Home button while the app is working in foreground and swipe up and kill the app in App Switcher, `applicationWillTerminate:` is called, regardless of there is a background task or not. But, if you click Home button only once, and make the app go into background first, and then double click Home button, swipe up and kill the app later, `applicationWillTerminate:` will be called only if there is background process is going on. Otherwise it will not be called. – erkanyildiz Mar 14 '17 at 18:41
  • @erkanyildiz I am seeing that for iPhone X, even killing the app as its in the foreground, the method is still never called. – hvaughan3 Jan 23 '18 at 19:38
4

As I know, there are 3 situations that your application will die.

  1. Terminated by the end user, you can do something in -[UIApplication applicationWillEnterBackground:], in which case, -[UIApplication applicationWillTerminate:] will NOT be called.

  2. Dropped by the system, such as memory not enough, you can do something in -[UIApplication applicationWillTerminate:], in which case, we do NOT know whether applicationWillEnterBackground: has been called;

  3. Crashed, nothing can be done except using some kind of Crash Reporting Tool. (Edited: catching SIGKILL is impossible)

DawnSong
  • 4,752
  • 2
  • 38
  • 38
  • 3
    applicationWillTerminate is being called when user terminates app – BaSha Jun 15 '17 at 07:09
  • @BaSha, you are correct for Xcode 9 and iOS 11. However, it did as what I said when I answered this question. – DawnSong Oct 12 '17 at 07:33
  • @BaSha No, it is not. Only sometimes. The documentation clearly states that this cannot be reliably used. – nickdnk Aug 18 '18 at 14:10
  • applicationWillTerminate is being called when user terminates app.But it is not being called when first application is entered in background state pressing home button and then user terminates application. – iosdev1111 Oct 09 '19 at 07:38
3

Source: http://www.cocos2d-iphone.org/forum/topic/7386

I copied my state saving code from applicationWillTerminate to applicationDidEnterBackground and also added a multitaskingEnabled boolean so that I only call state saving in applicationDidEnterBackground. BECAUSE, there is one instance on a multitasking device where applicationWillTerminate is called: If the app is in the foreground and you power off the device. In that case, both applicationDidEnterBackground and applicationWillTerminate get called.

Jonathon Hibbard
  • 1,547
  • 13
  • 20
1

As we know that the App has only 5 sec when -applicationWillTerminate being called. So If someone want to update the server at that point. Than use Synchronous call.

[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];

Note:- -applicationWillTerminate will not call if app is being killed from suspended state. Suspended state means app is not working anything in backgroupd. One of the solution for this is to use background task.

Gagan Joshi
  • 3,347
  • 2
  • 21
  • 32
0

Based on Andrew's test, I understand the docs for applicationWillTerminate(_:) to be meant as having the following clarifications:

For apps that do not support background execution or are linked against iOS 3.x or earlier, this method is always called when the user quits the app. For apps that support background execution, this method is generally not called [right away] when the user quits the app because the app simply moves to the background in that case. However, this method may be called [instead of beginBackgroundTask(expirationHandler:)] in situations where the app is running in the background (not suspended) and the system needs to terminate it for some reason.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
-2

// absolute answer applicationWillTerminate

func applicationWillTerminate(application: UIApplication) {

    print("applicatoinWillTerminate")

    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

step 1: command + shift + h (double click(tab))

step 2: move app top side (kill)

step 3: applicationWillTerminate Work

gowthaman-mallow
  • 692
  • 1
  • 6
  • 10
  • it not called the willterminate .. never go inside this function .. how to fix ? – MAS. John Jun 29 '17 at 10:39
  • This works for me, but only if the application is going from running to terminated. Specifically, "applicationWillTerminate" gets called if the user is currently using the application, then double clicks on home to kill the application. If the user clicks on home first and the application goes to the background, swiping the application out will not call "applicationWillTerminate". – ShannonS Oct 17 '17 at 19:12
  • We can not be sure if app will enter to that will terminate method, I noticed that my code from will terminate method is executed only when I do debugging, and there is a break point into that function. – Dragisa Dragisic Mar 18 '20 at 15:42