Determine if the App is terminated by the User or by iOS

Hello Team,

How can I identify if an iOS app has been terminated by the User or by iOS?

As per the documentation: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623111-applicationwillterminatewill get called irrespective of the fact the app has been killed by the User or by iOS.

Also, to note I'm not using any UIBackgroundModes in my application.


I've got a requirement where I want to save some data in NSUserDefaults only if the System(iOS) has terminated the app. Is there any way I can determine that?

Thanks!

Accepted Reply

OK, that may be possible. The basic strategy would be to record in persistent storage when you app moves between the background and foreground state. If your app is launched and your last record indicates it was in the foreground state, then somehow it was terminated unexpectedly.

There’s a bunch of gotchas to watch out for here:

  • The above assumes you’re not running in the background. If you can run in the background then you have to substitute becomes eligible for suspension for moves to the background, and becomes ineligible for suspension for moves to the foreground.

  • Last I checked

    -applicationWillTerminate:
    is called when the user terminates your app from the multitasking UI while your app is in the foreground. You should test this case and handle it explicitly.
  • Don’t store your flag in

    NSUserDefaults
    , but rather as a simple file on disk. Specifically, you should use the presence or absence of that file as the flag, rather than the content.

    Note User defaults are meant for general-purpose preferences, not for situations like this, where you need to understand the synchronisation semantics of your persistent storage.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

I think you're being overly optimistic concerning what the second paragraph of the Discussion for that method says.

In practice, -applicationWillTerminate IS NOT called when your application is terminated, either by the system or by the user, on any recent iOS version unless it was running a background process.


Suspended apps get unloaded from memory without additional callbacks.


The last time -applicationWillTerminate was called for apps normally was in iOS 3.1 or so, as the notification after -applicationWillResignActive, as the last call before suspension. In iOS 4 or later, it doesn't get called for that any more.

Use NSUserDefaults to write save-state bits in

applicationWillTerminate
when called - presumably it would be a (graceful) system kill in that case, rather than user, but not much you can do that will satisfy your 'requirement', otherwise.


Keep in mind, tho, what your app can do when may depend on app state before kill occurs. Be sure to test/test/test.

How can I identify if an iOS app has been terminated by the User or by iOS?

As others have mentioned there’s probably no solution to this. However, I’d like to get a better understanding of your actual goals. iOS apps are run by a process, and that process can end in only a limited number of ways:

  • The user removing the app from the multitasking UI.

  • The app calling

    _Exit
    , or something layered on that (like
    exit
    ).
  • The user moving the app to the background, by pressing Home, locking the screen, and so on. The system will respond to this by suspending the app and, later on, terminating the app if it needs to recover memory

  • The app receiving a signal that terminates the app, including many of the signals typically associated with a crash (

    SIGSEGV
    ,
    SIGABRT
    , and so on).
  • The user hard restarting their device.

Which of these scenarios would you consider to be the user terminating your app? And which iOS?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks Quinn for your inputs!


So, here's how I would like to categorize the scenarios:


App Terminated by the User:

  1. The user removing the app from the multitasking UI.
  2. The user hard restarting their device.
  3. The app receiving a signal that terminates the app, including many of the signals, typically associated with a crash (
    SIGSEGV
    ,
    SIGABRT
    , and so on).
  4. The app calling
    _Exit
    , or something layered on that (like
    exit
    ).


App Terminated by iOS:

The user moving the app to the background, by pressing Home, locking the screen, and so on. The system will respond to this by suspending the app and, later on, terminating the app if it needs to recover memory.


So my requirement is to save a state in NSUserDefaults ONLY if the App is terminated by iOS and not by the User.


Thanks,

Avijeet

OK, that may be possible. The basic strategy would be to record in persistent storage when you app moves between the background and foreground state. If your app is launched and your last record indicates it was in the foreground state, then somehow it was terminated unexpectedly.

There’s a bunch of gotchas to watch out for here:

  • The above assumes you’re not running in the background. If you can run in the background then you have to substitute becomes eligible for suspension for moves to the background, and becomes ineligible for suspension for moves to the foreground.

  • Last I checked

    -applicationWillTerminate:
    is called when the user terminates your app from the multitasking UI while your app is in the foreground. You should test this case and handle it explicitly.
  • Don’t store your flag in

    NSUserDefaults
    , but rather as a simple file on disk. Specifically, you should use the presence or absence of that file as the flag, rather than the content.

    Note User defaults are meant for general-purpose preferences, not for situations like this, where you need to understand the synchronisation semantics of your persistent storage.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"