5

Not sure why this is so challenging for me, but how can I detect when the user terminates the app? Because from what I'm seeing, Apple provides a lot of functions that might or might not be called when an app closes.

func applicationWillTerminate(_ application: UIApplication): Called when (most) apps are terminated, but not for apps that support background execution.

func sceneDidEnterBackground(_ scene: UIScene): Called when the scene enters the background, but can't differentiate between the app entering the background versus terminating completely.

func sceneDidDisconnect(_ scene: UIScene): I confirmed this is called if the user directly terminates the app, but if the app is put in the background and then terminated, it isn't called..

// EDIT: So I realized the above method (sceneDidDisconnect) is indeed the function I was looking for. I previously thought it wasn't being called in the latter case described above, but in actuality, it was. See the (soon to be) accepted answer as well.

Is there a function that's called every time a user terminates an app???

Eric
  • 569
  • 4
  • 21
  • 7
    No, there's no bullet proof way to know when the app will be terminated. And you should never rely on any termination functions to be called. Why? because app termination may not be graceful. For example the phone may be out of memory and the app is killed urgently. Or battery died. So best is to assume that app can be killed any moment without any prior warning, and thus do things you wanted to do on termination using other triggers, e.g. on state change, or just periodically – timbre timbre Aug 24 '21 at 17:52
  • Well good to know. Is there a way to see when an app is closed out after it was previously in the background? For example, if I exit an app (but don't terminate it), and then later go to my App Switcher and terminate the app? Alarmy is able to do this to notify people when they terminate their app if an alarm is set. – Eric Aug 24 '21 at 18:04
  • I don't know what they did, so I can just speculate that they may have used `applicationWillTerminate` in combination with other methods, e.g. background fetch (will cause the app to get started if it's not running, but limited to 30 min or so I believe), and maybe scheduled local notifications... – timbre timbre Aug 24 '21 at 18:19
  • 3
    I may be sensing an issue with your question. In iOS, **users** do not typically close an app. (They once may have, but most have learned they don't need to. But in your question you specifically addressed this three times. In iOS, typically it's the **OS** that terminates an app for a variety of reasons. Once you understand this, maybe you can be a bit more specific about *why* your app needs to care about this. You may find a b better way to handle your specific issue without caring about who or what terminated things - maybe like saving your apps state, recalling it when your app launches? –  Aug 24 '21 at 18:37
  • What are you trying to do? Alarmy is probably posting a local notification on a schedule, and just before it's about to fire, postponing it if the app is still running. – chedabob Aug 24 '21 at 19:46
  • Please see my EDIT. `func sceneDidDisconnect(_ scene: UIScene)` was the solution after all. – Eric Aug 24 '21 at 20:30
  • @chedabob I originally thought Alarmy was following your solution proposed solution, but then I realized there's really no way for them to postpone the notification if the app is still in the background (in which case the notification would be triggered incorrectly). – Eric Aug 24 '21 at 20:32
  • @dfd Yeah I think you are right that I am a little confused on the whole "termination" thing, but what I'm essentially going for is how to detect when the user basically enters the *app switcher* and up-swipes on the app to "terminate" it or close it out. For that, I've realized `sceneDidDisconnect` does the job. – Eric Aug 24 '21 at 20:36
  • @Eric Instead of editing the answer into your question, you should post it as an answer and then accept it so that your question doesn't look unanswered. I think you might even get a badge the first time you answer your own question. – Caleb Aug 24 '21 at 21:28
  • @Caleb Thanks, I will do that! – Eric Aug 24 '21 at 22:07
  • I upvoted your answer because it will help others. I come from a, uh, mainframe background followed by Windows and web - so yes iOS, while elegant with it's memory usage, is a bit of a paradigm change. It's gotten worse in ways with XIBs becoming Sotryboards and AppDelegates becoming SceneDelegates. Glad you figured out a solution! (BTW, my favorite iPad game features those annoying full screen 30 second ads at times - so I just force-quit and restart because it takes less time than watching a stupid ad.) –  Aug 25 '21 at 01:59
  • Haha clever "ad-free" solution. Sometimes turning on airplane mode can work too. – Eric Aug 26 '21 at 16:08

1 Answers1

3

func sceneDidDisconnect(_ scene: UIScene) ended up being the function I was looking for. It's called whenever the user manually "terminates" the app...

...although as @dfd commented

"In iOS, typically it's the OS that terminates an app for a variety of reasons (not necessarily the user)."

Eric
  • 569
  • 4
  • 21