applicationWillTerminate vs. applicationWillResignActive vs. applicationDidEnterBackground? When are they triggered exactly? [closed] - ios

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I know there exists a similar question but I think that question is a lot more general and does not answer on the specific details that I'm trying to find out.
I've read the Apple documents, but still I'm a bit confused on when exactly these methods are triggered. From the Apple documents, it seems there are the following state transitions that are possible for an iOS app:
App terminated in the foreground (for example double tap the Home button and swipe up the app): pretty sure applicationWillTerminate is triggered in this case, actually this is the only case that I'm not too confused about.
App switched to the background while still running in the background (for "apps that support background execution" to quote Apple documents): applicationDidEnterBackground is triggered? applicationWillResignActive is triggered or not?
Background running App gets terminated: applicationWillTerminate may(?) be triggered according to the Apple documents... so it may or may not be triggered at times?
App switched to the background and immediately suspended: applicationDidEnterBackground and applicationWillResignActive are both triggered?
Background running App gets suspended: applicationWillResignActive is triggered? Or nothing gets triggered?
App that "does not support background execution" gets switched to the background: applicationWillTerminate gets triggered according to Apple documents? But what exactly does this actually talk about?
App crashes in the foreground: nothing gets triggered in this case I guess?
Background running App crashes: also nothing gets triggered in this case right?
Background suspended App gets terminated: Again nothing gets triggered I guess?
I think the Apple documents are either somewhat vague or downright confusing in explaining those methods. Sometimes they talk about "apps that support background execution" vs. "apps that do not support background execution", sometimes they talk about "running in the background" vs. "suspended", sometimes they just say things like "the user quits the app and it begins the transition to the background state" or "incoming phone call or SMS message", which are real-world use-cases instead of technical concepts.
So anyone can help explain in more consistent technical terms that when exactly are those methods triggered in specific cases?
EDIT: Not sure why this question is deemed not "focused", as I'm trying to make use of those application delegate methods but after both some personal testing and reading official documents, I'm still at a loss when exactly those methods will be triggered and how may I use them reliably.
Maybe I can elaborate more by borrowing some stuff from PGDev's answer, so there are 5 states an iOS app can be in if I understand correctly:
Not running
Inactive
Active
Suspend
Background
And when the app changes state, some delegate methods may be triggered, but so far from the official Apple documents, it seems very confusing which methods will be triggered during which state transition.
For example I'm not sure what or if any method will be triggered when app goes from state 5 to state 4, and when app goes from state 5 to state 1, and when app goes from state 4 to state 1. Also from the official Apple documents it seems to say that applicationWillTerminate will be triggered if "apps that do not support background execution" are switched to the background, however I have not been able to get any kind of app to trigger applicationWillTerminate by just pressing the Home button.
As it currently stands, I'm not sure if I can reliably utilize those methods to do anything, that's why I hope someone can give a clearer picture on when exactly those methods will be triggered (and not triggered) apart from those vague descriptions in the official Apple documents.

Here is the detailed explanation of how the App Lifecycle methods work.
There exist 5 states in the the lifecycle of the app,
Not running — The app is not running.
Inactive — running in foreground + not receiving events
An iOS app can be placed into an inactive state, for example, when a call or SMS message is received.(Foreground + Not Running)
Active — running in foreground + receiving events
Suspend — running in background + not executing code
Background — running in background + executing code
Next there exist 7 delegate methods that are called whenever the above states are changed in the app's session.
Launch time
application:willFinishLaunchingWithOptions
Method called when the launch process is initiated.
This is the first opportunity to execute any code within the app.
launch process has begun but that state restoration has not yet occurred.
didFinishLaunchingWithOptions
Method called when the launch process is almost done and the app is almost ready to run. Final initialization.
Transitioning to the foreground
applicationDidBecomeActive
app has become active.
Transitioning to the background
applicationDidEnterBackground
This method is called when an iOS app is running, but no longer in the foreground
Transitioning to the inactive state:
applicationWillResignActive
exit from active state to another state
Each time a temporary event, such as a phone call, happens this method gets called
called when app moves to background
applicationWillEnterForeground
about to enter from background -> foreground
Termination
applicationWillTerminate
app is about to terminate.
Force quitting the iOS app, or shutting down the device
This is the opportunity to save the application configuration, settings, and user preferences.
Some flow examples of the order in which the above methods will be called.
Launch app — 1, 2, 3 — willLaunch + didLaunch + didBecomeActive
Press home — 5, 4 — resignActive + didEnterBackground
Open app from background — 6, 3 — willEnterForeground + didBecomeActive
Open task manager — 5 — resignActive
Phone call comes when app in foreground — 5 — resignActive
You can test the execution of the lfecycle methods using the above examples.

Related

How to get location updates in iOS even if the app is in terminated state or is killed? [duplicate]

This question already has answers here:
IOS Getting location updates when app terminated without using significantChange
(2 answers)
Closed 5 years ago.
I searched a lot for one week. I searched google for the same question and I was able to get something working. But location updates don't work for the suspended state. It only works for foreground and background states.
And I need location updates after terminated state also.
Please refer to applicationWillTerminate
By Apple documentation it says:
This method lets your app know that it is about to be terminated and
purged from memory entirely. You should use this method to perform any
final clean-up tasks for your app, such as freeing shared resources,
saving user data, and invalidating timers. Your implementation of this
method has approximately five seconds to perform any tasks and return.
If the method does not return before time expires, the system may kill
the process altogether. 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 when the
user quits the app because the app simply moves to the background in
that case. However, this method may be called in situations where the
app is running in the background (not suspended) and the system needs
to terminate it for some reason. After calling this method, the app
also posts a UIApplicationWillTerminate notification to give
interested objects a chance to respond to the transition.
If you want to have user's location when app is not in memory, short answer: Impossible.

iOS: how to detect when the UIApplicationDelegate state becomes "suspended"?

How can we detect when an iOS App has been suspended?
There is no method that mentions this in the official UIApplicationDelegate documentation.
These are the states that an App can have:
(source: apple.com)
Use case:
I want to log when an app stops running subsequently to being woken up due a location event. For example I have got an iBeacon that the app is montioring. I activate the iBeacon and the app gets launched successfuly in background (for 10 seconds). I would like to detect when the App stops running after these 10 seconds have elapsed. However there is no AppDelegate method that seem to allow to intercept this (please consider that I am investigate this specific case.
Previous question:
I had asked a previous similar question which did not get answered. Please find it here.
While I am unaware of any callback, you can query for the amount of background time remaining with:
NSLog(#"background time remaining: %8.2f", [UIApplication sharedApplication].backgroundTimeRemaining);
Theoretically, you can put this in a thread and execute custom code a second or so before your app terminates. See my blog post here for more info:
http://developer.radiusnetworks.com/2014/11/13/extending-background-ranging-on-ios.html
I think you won't get any feedback form Suspended state. Suspended means that app is in memory but no code is executing right now.
Documentation:
The app is in memory but is not executing code. The system suspends apps that are in the background and do not have any pending tasks to complete. The system may purge suspended apps at any time without waking them up to make room for other apps.
So in my understanding, if an app would give you a callback with something like applicationDidEnterSuspendedState it will be a paradox, cause Suspended state means that no code is executed.

Debugging and state restoration concerns of WatchOS WCSession sendMessage waking killed iPhone app

I'm trying to add simple WatchOS 2.0 functionality to my app to allow simple actions to be triggered on the watch and have an effect in my main app on the iPhone. All of this hinges by sending messages from the watch using WCSession's sendMessage method
[[WCSession defaultSession] sendMessage:applicationData
replyHandler:^(NSDictionary *reply) {
//handle reply from iPhone app here
DbgLog(#"reply received=%#", reply);
}
errorHandler:^(NSError *error) {
//catch any errors here
DbgLog(#"error received=%#", error);
}
];
Everything is working ok so far, the message is sent, the message is received, my app reacts correctly. I can even have my app backgrounded and everything seems to still work ok (I can see on the watch whether or not the iPhone has reacted to the messages as the iPhone will update the watch connectivity context which is then reflected back on the watch). I just want to start debugging the edge cases now.
My main two worries are...
How exactly can I debug the system waking up my app if it's been killed. I obviously can't spawn the process from Xcode, if i try to attach to the process it'll obviously be too late, ideally i'd like to be able to get break points set really early to see how things work. Worse case I can rely on lots of logs I guess and look at those. Just wondering if there's a good way of trying to debug this scenario?
Finally, what happens in this killed app being ran by the sendMessage being sent scenario with regards to state restoration. ie.
My app was running with the app in a certain state (A)
I press the home button to background the app, state encoding is performed for my app state (A) at that time.
The app then sits in the background.
I then force kill the app by stopping running it in Xcode.
Finally I then sendMessage from the watch causing the system to re-run the killed app.
At this stage I'd expect state restoration loading to occur, the message comes in and is processed changing app state to state B, and then the app goes back to being backgrounded.
My problem is that the app still has its state encoding saved in state A when it was originally backgrounded.
Is there any way I can force a new state encode to occur whilst backgrounded after I've finished processing the watch connectivity sendMessage?
What happens when I next open my app properly, does state restoration occur which brings us back to state A when having processed the watch sendMessage it should be in state B. I'm guessing its still running in the background so whatever has occurred when the app spawned the app in the background should persist and no new state restoration should occur. However what if the system kills the app again whilst backgrounded in state B. Does it appreciate this scenario requires a new state encode to save the new state B or does it just kill the app and do nothing. If so then when we finally do freshly launch it then we may again be heading back to app state A rather than B.
As an aside, having just started to try and debug this sort of thing, though without the ability to seemingly connect my debugger for this system re-ran instance of my iPhone app. I've noticed that when I do the sendMessage that should wake up the killed iPhone app, the watch app does NOT update properly, ie. the phone app doesn't fully perform the action that has been requested. I'm currently blind at what things have taken place in this state, but wonder if perhaps state restoration could be getting in the way. Is the message received, waking the app, trying to act on data that doesn't exist as no state restoration has occurred yet, then state restoration occurs.. the 2nd time i send the message from the watch the app behaves correctly, so its as if the initial message wakes the app up but for some reason doesn't correctly process the message. Once woke up properly however the next sendMessage is handled as normal.
Sorry I find the documentation rather vague on what occurs when the iPhone app is background re-ran from a sendMessage call. Anyone got any ideas? Your time as always is really appreciated! Cheers!
Background and State Restoration:
Your app which was launched in the background (then terminated) will never save state, because it never transitions from foreground to background (which is when state preservation happens).
From Preserving and Restoring State:
UIKit preserves your app’s state at appropriate times, such as when your app moves from the foreground to the background.
The reason why it doesn't save state is because it is launched directly into the background.
From The App Life Cycle:
In addition, an app being launched directly into the background enters [the background state] instead of the inactive state.
Debugging an app launched in the background:
As for attaching to your app when it is launched in the background from a terminated state, there's a question which already provides the correct approach for this scenario.
If you have specific questions about that, please leave a comment with the author of that answer.

What iOS app delegate methods does the springboard kill trigger? [duplicate]

What is the delegate method for detecting when application was closed.
I mean when user tap this button:
I know about method below:
- (void)applicationDidEnterBackground:(UIApplication *)application;
- (void)applicationWillEnterForeground:(UIApplication *)application;
But they work not as I expected in my case. For example I have used my app and I have navigated to some screen. In case when I lock screen and go back to app the app calls applicationWillEnterForeground but I don't need this, because I am still on this view (for example Test Screen View)and I don't need to check any changes. But in case if my app closed I begin to navigate from start app for example Home Screen. So if my app was closed and I am on Home Screen I need to check if in previous time I had some actions (for example if I passed test on Test Screen View) and present this view controller (ONLY IN CASE IF I CLOSED APP NOT JUST LOCKED IT OR ENTER BACKGROUND).
Thanks for help.
You can't detect this. From the iOS App Programming Guide ("App Termination" heading):
Important: The applicationWillTerminate: method is not called if your app is currently suspended.
Even if you develop your app using iOS SDK 4 and later, you must still
be prepared for your app to be killed without any notification. The
user can kill apps explicitly using the multitasking UI. In addition,
if memory becomes constrained, the system might remove apps from
memory to make more room. Suspended apps are not notified of
termination but if your app is currently running in the background
state (and not suspended), the system calls the
applicationWillTerminate: method of your app delegate. Your app cannot
request additional background execution time from this method.
You can't. When your app is killed in this manner, it is not told anything. The app is killed by the OS with no warning of any kind.
When your app enters the background, you have no way to know if will be started fresh or simply return to the foreground. Therefore you must properly handle things when the app enters the background.
When the app starts again, restore whatever state you need.
On iOS, you cannot check for that. That is: the process is SIGKILL'ed. One way I know that might be able to work relies on the fact that to kill an app, one has to suspend it first by pressing the home button.
Hence, you can gather your actions as the user uses the app, commit it to a saved place when the user suspends the app. If the user resumes, reset the list and start gathering info again. However, if the user suspends the app and you never get a resume, on the next app start, you can read the list and recover from there.
HTH
You can implement the -applicationWillTerminate: method of your UIApplicationDelegate delegate to respond to termination events. However, it's not guaranteed to be called in all cases, so you should not rely on it being called. According to the iOS App Programming Guide:
If your app is running (either in the foreground or background) at termination time, the system calls your app delegate’s applicationWillTerminate: method so that you can perform any required cleanup. You can use this method to save user data or app state information that you would use to restore your app to its current state on a subsequent launch. Your method has approximately 5 seconds to perform any tasks and return. If it does not return in time, the app is killed and removed from memory.
Important: The applicationWillTerminate: method is not called if your app is currently suspended.

iOS how to detect when app was removed from process

What is the delegate method for detecting when application was closed.
I mean when user tap this button:
I know about method below:
- (void)applicationDidEnterBackground:(UIApplication *)application;
- (void)applicationWillEnterForeground:(UIApplication *)application;
But they work not as I expected in my case. For example I have used my app and I have navigated to some screen. In case when I lock screen and go back to app the app calls applicationWillEnterForeground but I don't need this, because I am still on this view (for example Test Screen View)and I don't need to check any changes. But in case if my app closed I begin to navigate from start app for example Home Screen. So if my app was closed and I am on Home Screen I need to check if in previous time I had some actions (for example if I passed test on Test Screen View) and present this view controller (ONLY IN CASE IF I CLOSED APP NOT JUST LOCKED IT OR ENTER BACKGROUND).
Thanks for help.
You can't detect this. From the iOS App Programming Guide ("App Termination" heading):
Important: The applicationWillTerminate: method is not called if your app is currently suspended.
Even if you develop your app using iOS SDK 4 and later, you must still
be prepared for your app to be killed without any notification. The
user can kill apps explicitly using the multitasking UI. In addition,
if memory becomes constrained, the system might remove apps from
memory to make more room. Suspended apps are not notified of
termination but if your app is currently running in the background
state (and not suspended), the system calls the
applicationWillTerminate: method of your app delegate. Your app cannot
request additional background execution time from this method.
You can't. When your app is killed in this manner, it is not told anything. The app is killed by the OS with no warning of any kind.
When your app enters the background, you have no way to know if will be started fresh or simply return to the foreground. Therefore you must properly handle things when the app enters the background.
When the app starts again, restore whatever state you need.
On iOS, you cannot check for that. That is: the process is SIGKILL'ed. One way I know that might be able to work relies on the fact that to kill an app, one has to suspend it first by pressing the home button.
Hence, you can gather your actions as the user uses the app, commit it to a saved place when the user suspends the app. If the user resumes, reset the list and start gathering info again. However, if the user suspends the app and you never get a resume, on the next app start, you can read the list and recover from there.
HTH
You can implement the -applicationWillTerminate: method of your UIApplicationDelegate delegate to respond to termination events. However, it's not guaranteed to be called in all cases, so you should not rely on it being called. According to the iOS App Programming Guide:
If your app is running (either in the foreground or background) at termination time, the system calls your app delegate’s applicationWillTerminate: method so that you can perform any required cleanup. You can use this method to save user data or app state information that you would use to restore your app to its current state on a subsequent launch. Your method has approximately 5 seconds to perform any tasks and return. If it does not return in time, the app is killed and removed from memory.
Important: The applicationWillTerminate: method is not called if your app is currently suspended.

Resources