An app is relaunched by an SLC regardless of how it was killed provided when it was killed at least one CLLocationManager had called startMonitoringSignificantLocationChanges. There is one caveat to this - in version iOS7.0(.x) it was broken. It started working again in iOS7.1+.
To get this working requires that you complete a few steps.
- In you project capabilities you must enable the background mode location updates because you want to be woken in the background.
- You need to add the key NSLocationAlwaysUsageDescription to the info.plist containing a description of why you want to always be able to use location in the background.
- In the code you must request authorization from the user to always use location
- In the code you must request that location updates continue to be delivered while in the background
- In the code you must start monitoring for significant location changes
Here is an example:
AppDelegate,h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>
@property (strong, nonatomic) UIWindow *window;
@property CLLocationManager* locationMgr;
@end
AppDelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize locationMgr;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"app launching");
locationMgr = [[CLLocationManager alloc] init];
[locationMgr setDelegate:self];
// Added in iOS8
if([locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)])
[locationMgr requestAlwaysAuthorization];
// Added in iOS9
if([locationMgr respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
[locationMgr setAllowsBackgroundLocationUpdates:YES];
[locationMgr startMonitoringSignificantLocationChanges];
return YES;
}
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"app delegate received significant location change");
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:[[UIApplication sharedApplication] applicationIconBadgeNumber]+1];
}
@end
The first time you run the app on your device, click on OK to allow the app to use your location in the background when it is requested. Then double click the home button and swipe the app off the task switcher to kill it. Click home, then swipe up from the bottom of the screen to open the Control Center and turn on Airplane Mode, wait a few seconds, then turn off airplane mode. Watch the badge counter increment on your app.
It was launched by iOS on an SLC.
One gotcha I would like to add. If you create two CLLocationManager instances and call startMonitoringSignificantLocationChanges on both, then call stopMonitoringSignificantLocationChanges on one. Even though the other CLLocationManager will continue to receive SLC events while the app continues to run, when you app exits for any reason, it will not be relaunched.
It seems the last call before exit sets the relaunch behaviour.
start, start, stop, exit - app doesn't relaunch on SLC.
start, start, stop start, exit - app does relaunch on SLC.