iOS power states in simple English - ios

As far as I know there are 3 states an app can be in.
a) Foreground
b) Background
c) Sleep (which is a state of the whole device)
The difference between the first two seems simple. But what exactly is the third state? And when does it happen? Is it when the device is locked?
And, quite importantly, does this happen after a long time, or does the device go to sleep if the user doesn't use it for a second, and reawakes the moment there's user action?
I've read different and seemingly contradictory pages about it, so either they were referring to different states or I just misunderstood what they were saying.
What am I trying to achieve: several things. But one of them is a timer that will execute an action every 10 seconds, and if the device was asleep so timers didn't run - I want it to run at the earliest possible time. Should I set a timer for every second and check if 10 seconds have passed (so that if a user checks the time on the phone for one second, the action will happen) or will it work automatically even if I set the timer for every 10 seconds?

The application lifecycle and the potential states your app can be in are more complex than you have stated.
Apple has comprehensive documentation on the application lifecycle and includes this diagram:
The main states you need to be aware of are:
Foreground Active - your app is actively executing in the foreground (ie it is the onscreen app)
Background - your app is actively executing in the background
Suspended - your app is in memory, but not currently executing.
It is important to note that your app only executes in the background for limited durations and under specific conditions.
It will execute in the background briefly as you transition from active to suspended in order to give you a chance to perform any required housekeeping prior to being suspended
It will execute in the background in response to specific background execution modes and permissions, such as location updates, Bluetooth or streaming audio.
When many people talk of their app "being in the background", what they really mean is that it is suspended. The Background state is an executing state while the Suspended state is a non-executing state. While suspended your app is still held in memory and will resume executing where it left off when it resumes an execution state.
Timers do not fire when your app is suspended. That is, expiration or firing of a timer will not bring your app from the suspended to background execution state.
Your best strategy for tracking missed events is to record when an event should fire (ie the fire Date) and check if that is the past when your app enters the Foreground Active state.
When your app is the foreground app and the device screen locks, timers will stop "ticking", so your strategy of setting a one second timer is probably the best approach for that scenario.
E.g. You have a 10 second timer, with 5 seconds elapsed when the device sleeps. After waking the device a further 5 seconds will elapse before the timer fires.
Note, however, there is a good chance that when the user does wake the device they will open some other app your app will be suspended.
You should also be aware that your app can be jettisoned (removed from memory) at any time when it is in the Suspended state if iOS needs memory. In this case when the user re-enters your app, it will restart from the top-left Unattached state and any in-memory variables will be lost.

Related

Application does not run in background after 5 minutes. (iOS)

I'm working on an iOS application and I want the app to terminate after hanging in the background for more than 5 minutes and when the user opens the app again it should display the login. For now the app terminates immediately when it reaches the background and the login screen when the user re-opens the app. I did this by adding a property called "Application does not run in background" to the info.plist file and I set the value to "YES". As I mentioned at the start what I want to do is to terminate the app after 5 minutes in background but not immediately. And the login screen appearing after the user re-opens the app is working fine.
Application does not run in background property in info.plist
I guess you this is managed by the operating system that for how long the app runs in the background, and the os terminates it when it require resources to get free.
A workaround that could be done is, store the time value in UserDefaults whenever the app goes to background, and whenever the app comes foreground, check for the previous time value. If the difference is greater than 5 minutes, you may direct to login.
You can request background time when you are told that you are being suspended. I believe the max you will get is 3 minutes, not 5. That will prevent your app from being terminated, and keep your app getting CPU time during that time. (Which will use extra battery power.) You will get a notice when that time expires, and you can save your app state and log off at that point.
Search on "Extending Your App's Background Execution Time" in the Xcode help system or Apple's docs for more information. The overview section of that document reads:
Overview
Extending your app’s background execution time ensures that you have adequate time to perform critical tasks. For tasks that require more background time, use Background Tasks.
When your app moves to the background, the system calls your app delegate’s applicationDidEnterBackground(_:) method. That method has five seconds to perform any tasks and return. Shortly after that method returns, the system puts your app into the suspended state. For most apps, five seconds is enough to perform any crucial tasks, but if you need more time, you can ask UIKit to extend your app’s runtime.
You extend your app’s runtime by calling the beginBackgroundTask(withName:expirationHandler:) method. Calling this method gives you extra time to perform important tasks. (You can find out the maximum background time available using the backgroundTimeRemaining property.) When you finish your tasks, call the endBackgroundTask(_:) method right away to let the system know that you are done. If you do not end your tasks in a timely manner, the system terminates your app.
The key bits of that are:
"When your app moves to the background, the system calls your app delegate’s applicationDidEnterBackground(_:) method."
And "You extend your app’s runtime by calling the beginBackgroundTask(withName:expirationHandler:) method"
Note that you should really implement an app level "heartbeat" where the app sends periodic "I'm still here" messages to the server to keep the user logged in. Your server should log the user off if they miss more than one heartbeat message.

App terminates after about 5 mins after the pressing lock button

While my app is in the foreground if a user presses the lock button the app will resign from activity but should still be ready to start again when the user unlocks their phone. After about 5 mins or so my application ends up being terminated and when they unlock their phone they are back on the home screen. Is this expected behaviour? As far as I know I havn't experienced this situation until I started a new project. Am I doing something wrong here or forgetting some sort of setting?
The Operating System can terminate your application at any time to free resources for other processes that may need them or to conserve battery life.
"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."
(Source: Apple Developer - "The App Life Cycle")
To minimize the likelihood of this happening to your application, look at what processes are running and do what you can to stop/ pause them while the application is not in the foreground.
Regardless how quickly this happens, it's important to design your application to handle the situation where it may be terminated in the background as this is something that can and will happen. Save state and critical information, such that on next launch the user can continue where he left off.

make timer run on background iOS for more than 3 minutes

So I need this app to run timer for more than 3 minutes, and play a sound like very 45 seconds, most of the solutions here are just for less than 3 minutes on iOS. Is there a way to make it run all the time, unless the app stops?
After the research, I guess the solution is implement beginBackgroundTaskWithExpirationHandler
and stops it by giving a handler and set location update on plist?
As for audio, besides setting the plist, anything else need to do to play audio?
Swift how to use NSTimer background?
iphone - NSTimers in background
Run app for more than 10 minutes in background
No, in order to save all of us from apps that kill our batteries, Apple does not allow apps to continue to run in the background for more than a few minutes. There are only very special limitations (music playing apps, VOIP, navigation apps, etc.) which permit ongoing operation. In terms of details, this is described in About the Background Execution Sequence.
If you want to notify user of something at some future time, you can use local notifications. When you do this, though, you don't control whether your app restarts or not. Only if the user taps on the notification (assuming they even granted your app notification privileges at all), will the app be reopened. For more information, refer the the local notification discussions in UserNotification framework documentation. But note, this is not intended for alerts every 45 seconds, but rather for a significant notification scheduled for some future time.
For discussion of how one might marry local notifications with timers, see swift NSTimer in Background and this follow up question swift calculate time for timers running in background.

How to ensure iOS app doesn't remain suspended in the background indefinitely?

Our iOS app retrieves new app data every time it is freshly started i.e. not resumed from the background. App data is updated periodically every couple of months via web services so this is generally fine.
However, there may be edge cases where the user's iOS device - iPad, specifically - may keep the app suspended in the background for an extended period of time - potentially indefinitely.
Is it possible to mitigate this edge case by telling iOS "please release this app if it has been suspended for more than a few hours"?
The issue you describe is due to poor app design or a poor understanding of app architecture. If you need to refresh app data whenever the app becomes active you can simply call your update function off of the UIApplicationDelegate event (or register for a notification), specifically:
applicationDidBecomeActive:
Tells the delegate that the application has become active.
- (void)applicationDidBecomeActive:(UIApplication *)application Parameters
application
The singleton application instance.
Discussion
This method is called to let your application know that it moved from
the inactive to active state. This can occur because your application
was launched by the user or the system. Applications can also return
to the active state if the user chooses to ignore an interruption
(such as an incoming phone call or SMS message) that sent the
application temporarily to the inactive state.
You should use this method to restart any tasks that were paused (or
not yet started) while the application was inactive. For example, you
could use it to restart timers or throttle up OpenGL ES frame rates.
If your application was previously in the background, you could also
use it to refresh your application’s user interface.
After calling this method, the application also posts a
UIApplicationDidBecomeActiveNotification notification to give
interested objects a chance to respond to the transition. Availability
When the app is suspended it shouldn't be refreshing. Per Apple's documentation, unless your app has registered for one of the specific background processes, the app is essentially frozen until it resumes. There shouldn't be any network calls made.
However, if you DO want to kill the app once it's been suspended for too long, you could implement a hack that registers a background timer for 10 minutes, then after 10 minutes call some garbage code that you know will crash. Problem solved :)

write to database when ios app in background state

When iPhone app is in background state or when app is minimized, I want to monitor the duration of time the app is in background and on every regular interval like every 24hrs need to get updates from web server and write the modifications in my local database.
This monitor cycle will repeat as long as app is in background. Is this kind of task is possible in iPhone applications ? Could any body help me how can I perform these tasks when app is in background state ?
beginBackgroundTaskWithExpirationHandler: is the API to make the app in background for long tasks but how long will this support.
Background tasks are killed after 10 minutes time, so to answer your question: No, it's not without faking some kind of long term event handling through a significant location's update, and even then, you have no control over when exactly the events are sent. On the other hand, using APNS to alert the user to a change has the possibility of being ignored, but comes with regularity.

Resources