App not stopped when launched for background fetch from Xcode - ios

When I launch my app from Xcode with Background Fetch mode, it works. But it should stop when I call callback handler, or after 30 seconds.
But it does not! When I click Pause, I may see my main thread does not do anything.
Is it some xcode-specific issue, or do I misunderstand something about background fetch?

Apps running under the Xcode debugger are not subject to the same background execution time limitations as a released app.
For example, if you looped, logging UIApplication property backgroundTimeRemaining on a released app, your app would be terminated when this value reached zero. Under the debugger your app would continue indefinitely, reporting a zero value.

Related

iOS app getting killed in background - how to debug?

My iOS app gets terminated when put in background. I get the following logs in the device console:
Background Task 160 (""), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.
followed by
Background task still not ended after expiration handlers were called: . This app will likely be terminated by the system. Call UIApplication.endBackgroundTask(_:) to avoid this.
and the app terminates and restarts on resuming from background
The new metric kit background exit data (iOS 14) is also reporting that BackgroundTaskAssertionTimeoutExits are killing my app
On breaking on UIApplicationEndBackgroundTaskError, I get the following backtrace:
I have not implemented any background tasks myself but there are some third party libraries integrated in the app that do.
What is the right way to debug this?
If you did not start any background task, and you do not perform anything most likely some of your 3rd party frameworks are causing the crash.
Update to latest version of all your dependencies, to see if the issue was fixed.
If your issue is easily reproducible, try to disable them 1 by 1 to see which is causing the crash.
After that go on the library support page and see if there are any bugs for your issue and if not open a bug.
Start with the usual suspects, Analytics, Loggers and go on.
Have a look also at this thread: App is crashing on only iOS 13 in the background mode

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

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.

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

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

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