How to avoid iOS app being terminated by system too often when in background - ios

I'm building an iOS app for iOS 8 & 9 and I am facing the problem that when the app goes to background the system is terminating it after just 2 or 3 minutes.
My testing is easy:
I kill all running apps from my iPhone.
I restart my iPhone (to ensure no other apps are taking memory).
I launch my app.
I do nothing inside my app.
I press the "Home" button, moving my app to background.
I wait doing nothing else for 2 or 3 minutes.
I open my app again and surprise, the system has terminated it and now it is restarting as a new launch.
Some comments:
The app does not use CoreLocation in background neither any other service.
I've profiled the app, trying to understand if it is consuming too much memory. When moving to background, it consumes around 25Mb of RAM memory. I'm attaching a screenshot below.
This behavior has been tested on iPhone 5, 5s, 6, 6+.
In iPhone 6s and 6s+ seems to take a bit more time to happen, but still happens.
My question is: Do you know why would this be happening? anything I might not be considering or just forgetting?
I don't want to force my app to run in background by using CoreLocation or something similar. And I'm ok if the system kills my app eventually. What I don't want is that everytime I move my app to background the system terminates it.
Any hint or help will be appreciated.
Thanks,

All applications are automatically killed by the system
According the Apple documentation:
App Termination
Apps must be prepared for termination to happen at any time and should not >wait to save user data or perform other critical tasks. System-initiated >termination is a normal part of an app’s life cycle. The system usually >terminates apps so that it can reclaim memory and make room for other apps >being launched by the user, but the system may also terminate apps that >are misbehaving or not responding to events in a timely manner.
Suspended apps receive no notification when they are terminated; the >system kills the process and reclaims the corresponding memory. If an app >is currently running in the background and not suspended, the system calls >the applicationWillTerminate: of its app delegate prior to termination. >The system does not call this method when the device reboots.
In addition to the system terminating your app, the user can terminate >your app explicitly using the multitasking UI. User-initiated termination >has the same effect as terminating a suspended app. The app’s process is >killed and no notification is sent to the app.
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html#//apple_ref/doc/uid/TP40007072-CH2-SW1
You can track position but you will certainly see a blue status bar to indicate that an application use GPS tracking.
Maybe you can try to "wake up" your app in background with silent notification...
If it is not necessary to keep your app alive, trust the system...

Some error in inside your code. Please select debug Navigator before run your app... Now you can able to find your error..
Or too much memory also it will terminated..

Apps which are running in the background drain battery life faster, It gives you a bad perception of the device, instead of the app, because the average consumer has no idea that it's an app draining battery.
Thus iOS won't allow your app to run in the background, more than a few seconds. But there are some exception, an app can request extension to this by declaring that its starting a Background Task.
for more info you can check below links:
http://blog.dkaminsky.info/2013/01/27/keep-your-ios-app-running-in-background-forever/
http://www.speirs.org/blog/2012/1/2/misconceptions-about-ios-multitasking.html

Related

iOS Background Mode: After running location updates in the background, the app never terminates

I'm running location updates in the background. All works well:
On significant location the app is launched in the background
- appDidFinishLaunching(options:) is called as expected.
I start LocationManager startUpdatingLocation() and startMonitoringSignificantLocationChanges()
Locations are collected correctly.
After some time, I call stopUpdatingLocation()
My program at this stage doesn't need to do anything and no further code is executed
At this point the program stays idle. applicationWillTerminate is never called again. Is this expected? I'd hoped the app will shut down again as no location updates are required.
What's the expected behaviour? Should the app shut down or should it stay idle forever?
Once this happens, then if a user user opens the app or a significant location is received again, then appDidFinishLaunching(options:) is NOT called, but instead applicationDidBecomeActive.
Is there any documentation I can follow that supports the expected behaviour?
Yes, everything here is expected. There's a deleted answer from J.D. Wooder that correctly linked the documentation: "Managing Your App's Life Cycle." As a rule, background iOS apps are not proactively killed. They are only killed when system resources are needed. This is unpredictable, and the app typically will not receive a applicationWillTerminate message when it happens (because the app typically is not running at that point, and it won't be woken up just to kill it). Your app should handled both a cold launch (appDidFinishLaunching) and a warm launch (applicationDidBecomeActive).
Restarting an app from scratch is expensive, so iOS prefers to keep recently used thing in memory if there's no resource pressure. Apps that are doing nothing are very cheap. to keep around.
Note that iOS 13 has grown much more aggressive in killing apps in the background, and that the large cameras on new phones are leading to memory pressures that kill apps more quickly as well, so don't get too comfortable with running in the background for a long time. But it's also very normal.
Please see the iOS app Life Cycle,
appDidFinishLaunching will call only when app Launch,
applicationWillTerminate - called when app terminate from background
applicationDidBecomeActive - Called when app comes to foreground from background

iOS 12 terminates apps in the background for no reason

Starting from iOS 12 the CLLocationManager doesn't run endless anymore in the background. The app get's terminated without a crashlog at random times. This was working fine before iOS 12.
To demonstrate this problem I've created an sample app here
The demo app just launches an CLLocationManager and keep this running in the background. While running on the background we keep track of it by logging it. The problem is that the app get terminated by iOS. The demo app is created to demonstrate this problem.
Steps to reproduce
Run the app on the device
Grand access to locationmanager
Put the app to the background
Wait for 1-48hours
Result:
The app is terminated
App is terminated without any reason after random time.
Expected result:
The app is still running.
How it should work
This is confirmed by an Apple engineer:
Once the CLLocationManager updates are started in the foreground and you did all the work to have it running in the background, the location updates should run endless in the background until:
app is force quit
device is rebooted
app stops location updates
app releases the CLLocationManager object
app crashes
iOS terminates the app due to memory shortage,
the locationManager object is released, overreleased, or overwritten. You should make sure that your view controller is not being instantiated, which then resets the locationController class. If that happens when the app is in the background, you will restart updates, which will cause the app to be eventually suspended. You should make sure the locationController is a singleton.
app is crashing. Check to see if there are crash logs on the device you are testing
iOS is terminating the app due to memory shortage. In this case, you will find JetsamEvent logs on the device that shows your app being terminated. You can check the timestamps and locate the one that is around the time your app stopped working.
Updated answer:
Apple fixed this bug in iOS 12.2 beta 2 (16E5191d)
Original analyse and bug detection:
Together with Apple Developer Technical Support we have analyzed this issue with Sysdiagnose files. Following these guidelines you can install profiles to have more logging on your device. I don't know exactly how these logs work and where to find this issue, but Apple did this for me and came with this first analyse:
On the suspension event you observed on 2018/10/22 01:01:12:587, this
is what I see (about a minute after your last activity logging)
[CllocationManag:2725] Terminating with description:
{
owner = ;
target = rw.sp.flitsmeister.frameworks.CllocationManagerBackgroundTest; }
This is basically saing that your app was terminated, because the
system needed drive space, and killed a bunch of apps so it can delete
their /tmp and /Library/Caches directories. I have seen this process
to be a little more aggressive in iOS 12, but seeing you are on a
256GB device, and have ~179 GB free after the cleanup, I am finding it
hard to believe this was justified.
After sending some more sysdiagnose and reproduction cases Apple did his best to analyse and ended with the following conclusion:
Unfortunately I don’t bring good news.
It turned out that, currently in iOS 12 there is a new mechanism that
will terminate long running background apps periodically as the system
needs to free resources. At this time, this process is a bit too
aggressive, and I am working with the relevant teams to get this to
behave better.
So, at this point, I would like you to file a bug report. Explain the
symptoms. And make sure you upload the sysdiagnose files along with
the bug report. (I already sent yours in, but it doesn’t hurt to have
the new ones as well). And let me know the bug number please.
So this means that currently in iOS 12 you app won't run endless on the background. I've filled in a bug report, the number is 45581276 and will try to keep this thread updated.
I tried clearing out the /tmp and /Library/Caches directories when the app goes in the background without any change in behavior. I also tried the same periodically when the app processing background locations without any change as well.

Detecting iOS app background termination by system

What I'm trying to achieve is detecting when the system terminates an app while it is running in the background (not suspended). According to this article it can be done by process of elimination. One of the steps is deciding that user didn't force quit the app. I assume this is done by checking whether applicationWillTerminate was called. However, according to Apple's documentation this method can also be called by the system, so I'm not sure how it eliminates that option.
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.
Is it possible to detect background system termination, and if so, what am I missing here?
The App Programming Guide for iOS: The App Life Cycle says:
Suspended apps receive no notification when they are terminated; the system kills the process and reclaims the corresponding memory. If an app is currently running in the background and not suspended, the system calls the applicationWillTerminate: of its app delegate prior to termination. The system does not call this method when the device reboots.
In addition to the system terminating your app, the user can terminate your app explicitly using the multitasking UI. User-initiated termination has the same effect as terminating a suspended app. The app’s process is killed and no notification is sent to the app.
The above is consistent with empirical tests.
In that Reducing FOOMs in the Facebook iOS app article, they mention the force quit situation where the app did "receive a termination call the last time the app was open": That only applies if the app was actively running and the user force quit it. But if the user first returns to the home screen (or otherwise suspends the app) and then force terminates the app, you will not receive that termination.
Bottom line, if the app is suspended at the time it was terminated, I do not believe that you have any reliable way of knowing whether it was jettisoned due to memory pressure or because the user force quit. The force quit scenario contemplated in that FOOM/BOOM article clearly only applies if the app was running when it was force quit.

Is there a way to know when my app switches from Suspended to another state?

I'm having issues with my WKWebViews'cache being purged sometimes when a user hasn't been using my app for a while.
I guess, that's because iOS puts my app in Suspended and then a low-memory condition occurs so my app is purged.
I read Apple's documentation about The App Life Cycle - Execution States for Apps
Especially the part describing the Suspended state :
Suspended - The app is in the background but is not executing code. The system
moves apps to this state automatically and does not notify them before
doing so. While suspended, an app remains in memory but does not
execute any code. When a low-memory condition occurs, the system may
purge suspended apps without notice to make more space for the
foreground app.
Two questions here :
1) What does "purge" mean exactly ? The app is killed ? Or does it still appear on the app selector ( when double-tapping the home button )
2) Here we can see that there is no way to know when an app is going to be suspended. All right. But if a user comes back to the app, is there a way to know, then, that the app has been suspended ? I can't find any UIAppDelegate's method to do so, but there might be another solution ?
Purge - The purge command forces disk and memory caches to be emptied,
offering a ‘cold disk buffer cache’ which is similar to the state of
the operating system after a reboot.
Referenced from here
As per the documentation
applicationDidEnterBackground:—Lets you know that your app is now
running in the background and may be suspended at any time.
This is the only method which will let you know that method may will enter in Suspended State
also
application:didFinishLaunchingWithOptions: will let you now that
your app's launch process is almost done and the app is almost ready
to run.
The app is in the background but is not executing code
I think it's explained good by Apple, the app is still in memory but no background threads are executed since foreground app requires more resources. Maybe when memory is restored, your app can execute background code again if has not been killed by OS.
When low-memory condition occurs, you're app could be killed (purge).
Is there a way to know, then, that the app has been suspended?
When app is killed from OS, next launch is equal to a complete new restart of app. For this AppDelegate doesn't provide a method to achieve this. You could set a flag in UserDefaults when app goes in background and then make some logic on that flag.

Is there a way to know if and why iOS terminated your app?

I'm trying to debug an issue with my iPhone app that seems to be getting terminated while running on the device (it never happens in the simulator). The app is for iOS 8 only.
Once app enters the background (via the user hitting the home button) I start Significant-Change Location service. When a location updates happens while the app is suspended the system should put the app in the background where I then send an update to my server with the location. That operation is wrapped in a proper beginBackgroundTaskWithExpirationHandler to allow me the time needed to make the network call.
It appears though my app is getting terminated by the system because sometimes when I resume the app from the suspended state it is no longer in the view last seen when minimizing but is back at the root controller as if starting from a fresh launch. It does not appear to be due to a crash as I do not see it in the crash log nor is New Relic reporting such. The app is suspended though, not terminated, probably because it is getting launched again into the background from a location update.
The question is, is there a way to know that my app was indeed terminated by the system, and if so, for what reason(memory, exceeding background execution time, etc.) and at what time. Is there a log kept somewhere containing this information?
I'm under the impression I can not use applicationWillTerminate because the docs say this is not called when an app is suspend.
You may check in Devices page. (Shortcut is Command + Shift + 2)

Resources