You have two options here:
1) Regular location tracking.
This type of tracking works with kCLAuthorizationStatusAuthorizedWhenInUse
and kCLAuthorizationStatusAuthorizedAlways
authorizations. When CLLocationManager
started tracking location once it will receive location updates in delegate method locationManager:didUpdateLocations:
. App can go to suspended state, but when location manager receive new location app goes to background state and handles new location in delegate method. How to setup location manager:
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
// Setup location tracker accuracy
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
// Distance filter
self.locationManager.distanceFilter = 50.f;
// Assign location tracker delegate
self.locationManager.delegate = self;
// This setup pauses location manager if location wasn't changed
[self.locationManager setPausesLocationUpdatesAutomatically:YES];
// For iOS9 we have to call this method if we want to receive location updates in background mode
if([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]){
[self.locationManager setAllowsBackgroundLocationUpdates:YES];
}
[self.locationManager startUpdatingLocation];
}
2) Signification location changes tracking.
This type of tracking works only with kCLAuthorizationStatusAuthorizedAlways
authorization. It receives new location only each 500 meters, so distance filter and desiredAccuracy don’t work here. App can go to suspended state, and even can be terminated by system, but when location updates app goes to background state and receives location in delegate method locationManager:didUpdateLocations:
.
If app was terminated by system, it will be relaunched in background with UIApplicationLaunchOptionsLocationKey
key in launch options in didFinishLaunchingWithOptions
app delegate method. How to setup this type on tracking:
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
// Assign location tracker delegate
self.locationManager.delegate = self;
// For iOS9 we have to call this method if we want to receive location updates in background mode
if([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]){
[self.locationManager setAllowsBackgroundLocationUpdates:YES];
}
[self.locationManager startMonitoringSignificantLocationChanges];
}
You should notice that both of these methods does not guarantee that your application does not go to suspended state.
Also, if app was terminated by user (for example from app switcher by swipe) location tracking in background will not work.
UPDATE (corresponding to comments)
Here is my code examples that work for me:
For Regular tracking. Run the example, provide access to user location, tap Start button to start location updates. To test locations in simulator choose in simulator menu Debug > Location > Freeway Drive. Now you can push app to background by home button (Command+Shift+H). Leave simulator for more than 10 minutes, and all this time app will receive locations. When you return to app you will see red pins on the map.
For Significant changes. Run the app and test by the same way as for previous example.
Monitoring Significant changes can be started only by method [self.locationManager startMonitoringSignificantLocationChanges];
UPDATE (iOS 11)
Changes to location tracking in iOS 11
iOS 11 also makes some major changes to existing APIs. One of the affected areas is location tracking. If your app only uses location while the app is in the foreground, as most apps do, you might not have to change anything at all; however, if it’s one of those apps that continuously track user’s location throughout the day, you should probably book some time this summer for making some changes in how you do the tracking and testing possible usage scenarios.
follow this link: https://mackuba.eu/2017/07/13/changes-to-location-tracking-in-ios-11/