I have an application that runs on background because it's needs to use Location Update. however, since i don't want to consume battery. I would like to make sure that all view controller is unloaded when app switch to run on background.
Forcing your view controller to unload is not going to save any battery life. It's best to let the operating system worry about taking your app out of memory when it needs to. If you're using the background mode that notifies your application when the user has travelled a significant amount you need to worry about this even less since your app is not actually running in the background but only given a chance to respond to location changes. If you're using the constant location background mode (for GPS apps, etc.) this is a little bit more of an issue.
You don't need to unload the view controllers, but you do need to turn off location updates. If you are starting location updates in your App Delegate, put in something like this:
- (void)applicationWillResignActive:(UIApplication *)application
{
[myLocationManager stopUpdatingLocation];
}
You can also do this in the viewWillDisappear: method if your location manager is started in a different place than the App Delegate.
Related
My app supports background location updates (specifically with significant location monitoring).
Do I need to prevent UI (via controllers etc.) from loading when I identify that the app is in background (application.applicationState == UIApplicationStateBackground)?
My intention is to avoid heavy UI loading (it's a BIG app) in background, that might waste all the limited time I have in background to actually respond to the location update.
For example (in ObjC, but the question is also for Swift), let's say I have some RootViewController which initializes and holds the whole controllers/view hierarchy, should I, in the viewDidLoad do:
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
// Root view controller loaded while in background, so doing only background stuff
[self justDoBackgroundStuffWithoutUI];
} else {
// Root view controller loaded normally, so loading normal UI
[self initializeUIAndChildControllers];
}
? Or should I just "trust" iOS to ignore all of those UI tasks, because it will know it's in a background state?
You can ignore those and let the OS handle that, just be careful if you have long running BG tasks, they may or may not have time to complete so it is best to very careful as it won't allow you to run tasks forever.
Updating UI in background is unnecessary and confusing and non-efficient.
unnecessary because there is no added value to the user who's not using the app. A simple doing of things in viewWillAppear would suffice.
confusing because users maybe expecting to see changes themselves as the screen is appeared, I don't know of your app, but this is more of a business choice. Maybe you have something similar in the manner of displaying changes like gmail/whatsapp and you want users to see the new emails/messages.
non-efficient because you are just doing something battery consuming too early. You even said "heavy UI loading". What happens if the location changes again and again and again? could the changes be overridden in the sense that they are no longer necessary or you will always need the changes regardless.
To summarize: I'm not saying don't do any UI updates, every app has a sweet spot. Likely you won't need to do most of them and lazy loading the changes ie upon loading screen seems to be the better way. Though I'm sure there are some advanced guidelines which I'm unaware of. Hopefully other answers would will come.
In my app I'm using location updates in the background and this works without a problem. The issue is when the user doesn't need the location updates and goes out of the app, the app is still running in the background. I added some code to the appdelegate method:
- (void)applicationDidEnterBackground:(UIApplication *)application
Here I set location manager to stop updating location and also set it to nil. This doesn't solve the problem.
Is there a way for the app to behave like a normal app when the user doesn't need background updating? In this version is frustrating for the user to see the location arrow in the status bar even if the location is not updating. The location manager is stored in a singleton, so there is only one instance of manager in the whole app.
I'm making a background tracking GPS app for iOS 7.0+.
I'm having issues when tracking position while in background, it's killed after exactly 5 minutes, even if we are in the middle of a highway, with 1 location per second. It's not killed when constantly in active state.
This seems to occur only on iOS 7.0 version, not on later versions.
I already registered the plist location background activity.
I need maximum accuracy and shortest update time, so I'm not using the significant change method but the basic startUpdatingLocation. This application is used mainly plugged inside a car (no mercy for battery).
I set the location delegate to the app delegate so it's less subject to be deallocated.
Even with all of this done, it's still impossible to take this app alive in background more than 5 minutes.
I'm fighting on iOS which always find a way to terminate my app, even with app state restoration.
So the question is, is there a way to know why my application is killed ?
List of threads that didn't help me or does not respond to my needs, and that I already visited :
How to keep GPS app running in background without pauses
iOS Multi-Tasking Track GPS Location
Periodic iOS background location updates
The system will not tell you why the app was terminated.
I set the location delegate to the app delegate so it's less subject to be deallocated.
The delegate has no effect on whether the location manager is deallocated or not. You must keep a strong reference to the location manager itself.
I have an app which I want to recover from being killed while running in the background.
What seems to happen is that if the app is killed in the background due to memory pressure, on re-entering the app the app returns to the root view controller.
It appears from testing that neither viewWillAppear or viewDidLoad are called on the root view controller in this case, therefore I cannot execute any code this way on resume.
My question is which methods are called in the above scenario and, ultimately, how can I send a message to the root view controller to handle the case where the app is restarting after having been killed in the background ?
If your app is killed due to memory pressure then you will be re-launched fresh. This is certain.
If you want to restore your state in that case it's up to you.
You can use the state restoration facilities built into iOS 6. I haven't used them yet so I don't have specific tips for you.
You need some way to save your navigation state (modal VC that are on-screen and/or navigation stack) as well as the state data for each VC that's on-screen) plus any global application state data.
UIApplication Protocol reference
https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html#jumpTo_9
delegate method didFinishLaunchingWithOptions is called when application restarts
G'day iOS Guru's,
I have searched extensively for an answer, but can't find one (I bet the first response to my question will be to another similar question, but I cant find it).
Anyway, my problem is that I am running a simple map app that the user can drop pins on the map with a customised circle overlay around the dropped pin.
When the app goes into the background (iphone locked or home button pressed), if I re-enter the app within ~ 5 mins, the pins are still there and the app reopens to the last screen.
All good.
However, if I leave the app in the background for longer than 5 mins, the app restarts and all the pins are lost.
I have "Application does not run in background = NO" in the plist, and also enabled "App registers for location updates" under Required background modes.
How can I prevent the app from restarting after it enters the background and load the last opened view?
iOS can, and will, terminate your app while it's in the background if it needs additional resources to carry out whatever's going on in the foreground.
You need to ensure that your data is saved/archived when your app is terminated, and unpacked when re-launched so as to go back to where the user last was. The traditional way to do this is to use the applicationDidEnterBackground method, which is called when your app is suspended. You can then save all the data you need in order to resume cleanly in case your app is later terminated.
However, if you're targeting iOS 6 and upwards you can take advantage of a new feature - State Presumption & Restoration (link to documentation). State restoration off-loads some (but not all) of the heavy lifting onto iOS, and it can automatically snapshot your UI and provides easier ways to preserve and restore data.
in your AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
// Save your data
}