How much time an iOS app is guaranteed to stay in the background without being removed from the memory? - ios

I have a Swift iOS app consisting of 3 view controllers – the initial one with a tableview, the second one with the chosen element and ability to create a new time session and the third one with the actual timer for the session (let’s call it the timer vc).
In this case, the focus is the timer view controller. However, the question is not about the timer itself. It works both in foreground and background mode. The problem is this:
The app goes background. Then over a certain fixed period of time, it receives a local notification – a reminder to go back to the timer vc and save the results. Most of the time, it works fine but sometimes when you go back to the app (through notification), it opens the initial vc with the tableview instead of the timer vc, which seems like the system terminates the background app after a while and then reopens it when you go back through the notification. In this case, all the data from the timer vc are obviously lost since the app logic requires that the user save the data after the session is finished.
What I think, the essence of the problem may have to do with how long the app can stay in the background without being terminated or suspended (If I’m not mistaken, in this state, all the current data associated with the app are removed from the memory). I mean, when you set the notifications to be triggered like every 1, 5 or 10 minutes, everything seems to be fine. However, when the notification is set for 30 minutes or more, the mentioned bug seems to appear from time to time (especially when testing on an actual device instead of a simulator). For the most part, it appears if the device storage is almost full - under 1Gb of free space). Which leads me to believe that this may also be a memory management issue.
How to make this timer vc run in the background as much time as needed? Also, does anybody know how much time an iOS app is guaranteed to stay in the background without being removed from the memory? Thanks a lot.

There is no guarantee of your's app execution time when it is in background mode. The operating system can suspend it anytime, Operating system has the responsibility only to notify your app which you will receive in the app delegate.
For setting up the local notification, you need to get the help from OS only. You can't rely on your app's execution in the background thread. For scheduling and handling of local notifications, you can go through the following documentation.
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SchedulingandHandlingLocalNotifications.html#//apple_ref/doc/uid/TP40008194-CH5-SW1

Related

Application starts from Home Screen if app remains in the background for more than 30 seconds instead of showing the screen when it went to background

My iOS application is kind of messaging app, so user can send audio, video, images, etc. When user typing the message and app went background for more than 30 seconds then app launches from Home screen and all that messages, everything will be lost. Before 30 seconds app launches at the exact point where it went background. So how to do that same after 30 seconds also, at least I should maintain this state for 30 minutes.
Is using background process and schedule task will be a good method here in iOS 13+?
I particularly don't want to do anything on the background but when app comes from background to foreground within 30 minutes I want to maintain that state.
Messages Disappearing
Well, first of all, why are all the messages lost? if your trying to make a snapchat like experience where the messages disappear after you see them then that's fine but otherwise it might be worth adding a local storage for these messages using CoreData.
Cause
The main issue, after a little while iOS will but an app to sleep so to say, in this scenario it will remove all temporary data within your app, this means when you re-open it it will start from the beginning, it does this to save memory.
Solution
There are a few ways to solve this, you could use State Restoration
For a beginner though this could be quite tricky as the documentation on it is quite sparse.
Another option would be to save the last screen in UserDefaults and then when the app re-launches you can use the value to push the last screen the user was on. For both these solutions though you will need a way to persist the messages and re-fetch them (a database) CoreData would probs be your best bet
I do personally think State Restoration is the best option especially since it sounds like that's exactly what you want to do:
but when app comes from background to foreground within 30 minutes I want to maintain that state.

Questions about app state after tapping on app icon after apps enters suspended state

I’m putting an app into background.
Assuming that I’m not doing anything to keep the app alive in the background, then the app goes through suspended state in a matter of 5 seconds. Right?
What happens if I then tap on the app icon? That’s not suppose to trigger a didFinishLaunch right? It will just bring me back to the last screen I was at and also trigger didbecomeActive & willenterforeground notifications. I won't be getting any other callback. Right?
Assuming there is no restart of the phone, point 2 is true even if there are hours between me tapping home and then tapping back the app icon. Right? Does it also persist device restarts but not force-restart?
The only time I won’t be brought back to the screen I was at (before hitting home) is if the device receives a memory warning and my app is flushed out of suspended state. At this point tapping on the app icon will result in didFinishLaunch. Right?
(I’m asking all of this because sometimes after putting the app in the background and tapping the app icon again (e.g. 10 minutes later), the app is going through it’s launch phase. Most of the time it just goes back to its previous screen)
I've already seen Will ios terminate the app running in background after a specific time? but that doesn't address all aspects I want.
It will just bring me back to the last screen I was at and also trigger didbecomeActive & willenterforeground notifications.
Right, if your app was not terminated in the background.
I won't be getting any other callback.
Not necessarily true. If you were summoned to the front by a local notification, for example, you'll also get an event about that.
Assuming there is no restart of the phone, point 2 is true even if there are hours between me tapping home and then tapping back the app icon.
Not necessarily. The app might well be terminated silently in the background.
Does it also persist device restarts but not force-restart?
Absolutely not. How can the app run when the device is off? Shutting down the app terminates every app.
I’m asking all of this because sometimes after putting the app in the background and tapping the app icon again (e.g. 10 minutes later), the app is going through it’s launch phase
It's not a matter of time. The watchdog process is constantly combing the suspended apps looking for the ones that take up too much memory so that other apps can run. You must not be surprised if yours is one of them.
You can come back to the front launching from scratch or by coming back to life from suspension; it's the most basic fact of iOS app life! You just need to accept it.
But there are lots of things you can do to reduce your chances of being terminated in the background. Giving up memory-consuming objects as you background is first on the list.

iOS: Determine if another app becomes active

My app needs the device location with an accuracy of about 10 meters. If the app is launched, it usually takes e.g. 10 sec to get the required accuracy. This delay is OK. However when the app is „in use“ (see below), the delay should be less, e.g. 1 sec.
The problem is the following:
When the user switches off the display, the app transits from the active state to the background state (and the delegate methods applicationWillResignActive and applicationDidEnterBackground are called).
Normally, location updates are not done in background. So, next time the app transits from background to active state (delegate methods applicationWillEnterForeground and applicationDidBecomeActive are called), the location manager needs again e.g. 10 sec to reach the required accuracy. This delay in unfortunately not OK.
To avoid it, the app could do location updates in the background. This works fine.
The disadvantage is that these background location updates continue, even if the app is no longer used, because the user pressed the home button and switched to another app. This is disturbing at least for 2 reasons: The GPS hardware is unnecessarily active and uses power, and the user is notified that my app is using the device location although this is no longer required.
My question thus is:
Is it possible to determine if another app becomes active?
If so, background location updates could be switched off.
Is it possible to determine if another app becomes active?
No, your app only knows if it's in background or in foreground handling delegate events. Know if user opened another app or is in the home screen is not possible.
These background location updates continue, even if the app is no longer used, because the user pressed the home button and switched to another app.
I think you're right. You could start a timer when application goes in background and update localization only for an estabilished period (one minute?). Then, at the end of timer count save last localization coordinates. Timer is used to avoid unnecessary updates, then if user doesn't open again your app after a reasonable time, maybe it's because he's using other apps or he locked the device.
When the app comes to the foreground again, if timer is still active you're good. Otherwise show last localization saved and show a small "banner" to advise user that localization could not be accurated for the first 10 seconds (until when required accuracy has been reached)

Appending data inside a tableView in the background - iOS

My app works like this - you press an uibutton and it starts appending data inside a tableView with a specific delay, cell by cell. Sometimes it may take hours to append, because of the manually set delay parameter.
The problem is each time i switch it to background - the app gets suspended after several minutes (up to five usually) and the whole process breaks.
Is there any approach to handling this situation?
Thank you.
That's the designed behavior, an app return to background normally only have very short active time, then it will be suspended, but there are some exceptions:
Apps that play audible content to the user while in the background, such as
Music player app
Apps that record audio content while in the background
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
Basically speaking, if your app need to interact with outside for resource that can not be generated inside your app, you can apply for background running.
Any every app can legally apply a background task to run for a short time when the app enter background mode.
In your case, even if you implemented the background running, your app will possibly be rejected. If your app is doing the adding to table action controlled by a timer, you should be able to simulate the behavior yourself.
save a the system time stamp locally, maybe in UserDefault
when app launch or enter foreground, get the system time, you can calculate the time difference and figure out how many actions you should take and perform that with a batch action.
after that, clear the saved time stamp ensure next time your data won't be messed up.

IOS: forcing update before app becomes visible

I have a timer in my app, and I want it to appear to be running while my app is on the background. I'd like that if the user presses the home button when the timer shows, for instant "01:11:11" and then goes back to the app and it becomes visible to him 10 minutes later, to see the timer as "01:01:11", however I get a split second where it shows the last state when the app went to the background ("01:11:11") before it starts updating from the correct time.
I assumed that I could correct this by updating the state of my timer in "applicationDidBecomeActive" and it did work on my simulator in Xcode but not on my Ipad.
I'm using cocos2d for my drawing and this is what I'm doing in my applicationDidBecomeActive:
CCScene *s=[director_ runningScene];
GameLayer *l=[(GameLayer*)[s getChildByTag:GAME_LAYER_TAG];
if (l!=nil) [l myUpdate];
I don't think it's relevant to the problem though because myUpdate does get called but I still have that split second glitch on my Ipad, as if it starts back from its last state no matter what.
In apples clock app, in applicationDidEnterBackground it hides the timer text, so that when the app comes into the foreground you see a blank UI for the split second where your app is loading the new timer data in the UI. Also, you may want to call some of your applicationDidBecomeActive code in applicationWillEnterForeground, which is called first. But keep in mind, applicationWillEnterForeground is not called when the app first launches.
There will always be a delay between when your app comes into the foreground, and when the UI updates. Theres no way to fix that, so you might as well use what apple uses to get around the issue.
Well I tried to hide my UI in both applicationWillResignActive and applicationDidEnterBackground. Since applicationWillResignActive is called first and before going into preview (double click on HOME) it causes a "not so pretty" preview but I thought at least it would solve my original problem. It didn't (not, on my IPad). It looks like the system takes the screen shot even before applicationWillResignActive.
I checked the timer in the official clock app and I see the clock is updating even when the app is in the background (in preview), so they "cheat" anyway...

Resources