What is best iOS GPS (CLLocationManager) battery saving technique - ios

Ive written a GPS app for iOS 10 a while back. Ive gotten it to the point where its stable and working as expected and now I want to go after
battery saving techniques. The app sends GPS locations every 5 minutes right now but I could be flexible on how often I send the GPS locations, as long
as they aren't sent too infrequently. My app requires 'best' or '10m' GPS location setting as well which I know uses a lot of power, but I cannot use the 3km setting per my requirements (which I know would save more power).
From what I gather and reading the docs and playing with code to make it work, it seems that there are 2 techniques:
set pausesLocationUpdatesAutomatically = YES in combination with UNLocationNotificationTrigger
allowDeferredLocationUpdatesUntilTraveled:timeout:
Number 2 apparently does not work at all based on this article in iOS 10 and 11.
Number 1 gives me sporadic results when I log it to my server. Sometimes it works, sometimes Ill get a single GPS point in the middle of nowhere (without seeing a pause or resume log message) and then later it starts to work, other times it does not seem to work at all.
Sometimes Ill see 2 pauses back to back within the same second.
Other times Ive seen it resume locations back to back (minutes apart) without ever seeing the pause log message. And other times I see the pause log message and minutes later (or a while later) resume GPS sends without seeing a 'resume' log message.
- (void) setGPSBatterySavingTrigger
{
if (IS_IOS_10_OR_LATER && ([g_prefs getGPSAuthStatus] == kCLAuthorizationStatusAuthorizedAlways))
{
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(g_locMgr.getLastLocation.latitude, g_locMgr.getLastLocation.longitude);
CLRegion *region = nil;
float radius_m = 150.0;
region = [[CLCircularRegion alloc] initWithCenter:center radius:radius_m identifier:#"pauseLocationsCenter"];
if (!region) {
[logger log:TSERVLOG :#"pause radius failed at radius <%f>", radius_m];
return;
}
region.notifyOnEntry = NO;
region.notifyOnExit = YES;
UNLocationNotificationTrigger *trigger = [UNLocationNotificationTrigger
triggerWithRegion:region repeats:NO];
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = PROG_NAME;
content.body = #"GPS Restarted";
//content.sound = [UNNotificationSound soundNamed:nil];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"GPSTextNotify" content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] removeAllPendingNotificationRequests];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError *error)
{
if (error.code)
{
[logger log:TSERVLOG :#"UNUserNotificationCenter addRequest FAILED <%#>", error.localizedDescription];
}
}];
}
}
- (void) locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager
{
[logger log:TSERVLOG :#"===== JME GPS PauseLocationUpdates at <%#> <%f, %f>",
[mydate getCurrentDateTimeStr], self.getLastLocation.latitude, self.getLastLocation.longitude];
[self setGPSBatterySavingTrigger];
}
- (void) locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager
{
[logger log:TSERVLOG :#"===== GPS ResumeLocationUpdates at <%#> <%f, %f>",
[mydate getCurrentDateTimeStr], self.getLastLocation.latitude, self.getLastLocation.longitude];
}
Bottom line questions:
Has anyone been able to use either of these to get battery saving + GPS working reliably in iOS 10+?
If not, what combination of things did you do to get it to work 100% of the time while saving battery life?
Am I missing another technique that does work? (NOTE my requirements cannot use the 3km setting)
Thank you for your input!

Related

How can I get high accuracy location every 5 seconds or when user moves a threshold without draining the battery?

I have a location app that needs to get accurate location periodically. Currently I am getting constantly getting location in didUpdateLocation but I only ever log the location every 5 seconds. I am interested in a solution that gets accurate location periodically or on signification change. I would like either or both of these scenarios:
(by very accurate, I need 10m of desired accuracy)
Get a very accurate location every 5 seconds
Notify/callback if user moves a threshold ( eg moves 5 - 10 meters)
The app needs to work when backgrounded as well and location must still be logged if user switches to another app.
I was considering turning on/off location every 5 seconds but was not sure if that is the best practice. I also know there is also allowDeferredLocationUpdatesUntilTraveled but I believe that only applied to backgrounded mode. I would appreciate a solution that saves battery when the app is in use and in background mode. Please share your solutions and best practices for my use case.
I did write an app using Location services, app must send location every 10s. And it worked very well.
Just use the "allowDeferredLocationUpdatesUntilTraveled:timeout" method, following Apple's doc.
Steps are as follows:
Required: Register background mode for update Location.
Create LocationManger and startUpdatingLocation, with accuracy and filteredDistance as whatever you want:
-(void) initLocationManager
{
// Create the manager object
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
_locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
_locationManager.desiredAccuracy = 45;
_locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[_locationManager startUpdatingLocation];
}
To keep app run forever using "allowDeferredLocationUpdatesUntilTraveled:timeout" method in background, you must restart updatingLocation with new parameter when app moves to background, like this:
- (void)applicationWillResignActive:(UIApplication *)application {
_isBackgroundMode = YES;
[_locationManager stopUpdatingLocation];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[_locationManager startUpdatingLocation];
}
App gets updatedLocations as normal with "locationManager:didUpdateLocations:" callback:
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// store data
CLLocation *newLocation = [locations lastObject];
self.userLocation = newLocation;
//tell the centralManager that you want to deferred this updatedLocation
if (_isBackgroundMode && !_deferringUpdates)
{
_deferringUpdates = YES;
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
}
}
But you should handle the data in then "locationManager:didFinishDeferredUpdatesWithError:" callback for your purpose
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
_deferringUpdates = NO;
//do something
}
NOTE: I think we should reset parameters of LocationManager each time app switches between background/forgeround mode.
Hopefully this should help

Region Monitoring Glitch on iOS 7 - Multiple Notifications at the same time

I have been developing region monitoring on iOS for about 2 months. Recently we have found a glitch where all the regions within a certain radius (about 4.7KM or 4700 meters) triggered at the same time. The current location of the device is not even close to any of the regions. I am not sure what could have triggered that event. I have searched through StackOverFlow, Apple Developer forums and etc, I haven't find any similar issue with what I am facing.
In the app that I am developing, we are monitoring 8 regions within the City (Kuala Lumpur). On one instance, my colleague found out that there were 4 regions notification triggered on his phone at the same time. Below is the map showing his location, all the monitored regions, the potential radius that triggered the 4 region notifications.
The green marker is the location of the device when receiving the notification.
The blue circle is the potential radius of the device (about 4700 meters) which is covering 4 regions that send the notification to the device.
The red circle is the radius for each of the region.
There are 2 other regions on the map which never send notifications (never cover under blue circle)
Screen shot of the triggered notifications:
Here is my code for location Manager:-
CLLocationManager *locationManager = [LocationTracker sharedLocationManager];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = kCLDistanceFilterNone;
Here is my code for didEnterRegion:-
-(void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region{
NSString* message = [NSString stringWithFormat:#"Message"];
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateBackground || state == UIApplicationStateInactive)
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate date];
NSTimeZone* timezone = [NSTimeZone defaultTimeZone];
notification.timeZone = timezone;
notification.alertBody = message;
notification.alertAction = #"Show";
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
Note: This issue does not happen every time, it only happens once in a while. The 4700 meters is the radius that I came out with after analysing the location of the 4 triggered regions. I am not sure if this is a glitch on my code, on the iOS or there is a problem on the local telco in my country. In the latest version of the app, I am adjusting the distanceFiter to 10 and we are testing it right now to see if this will solve the issue.
//locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.distanceFilter = 10;
The method didEnterRegion never return the location of the user, I am not able to filter out the potential bad location with a big radius like the example I show above. What I can do to solve this glitch?
Any developer who is facing the similar issue, please come forward and share your experience and solution to solve this issue (if there is any). Thanks.
I have found a fix for this strange bug. We have tested for over 1 week and so far we haven't see the same bug again. Here is the solution:-
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
NSLog(#"didEnterRegion");
CLLocation * lastLocation = [manager location];
BOOL doesItContainMyPoint;
if(lastLocation==nil)
doesItContainMyPoint = NO;
else{
CLLocationCoordinate2D theLocationCoordinate = lastLocation.coordinate;
CLCircularRegion * theRegion = (CLCircularRegion*)region;
doesItContainMyPoint = [theRegion containsCoordinate:theLocationCoordinate];
}
if(doesItContainMyPoint){
NSString* message = [NSString stringWithFormat:#"You are now in this region:%#",region.identifier];
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateBackground || state == UIApplicationStateInactive)
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate date];
NSTimeZone* timezone = [NSTimeZone defaultTimeZone];
notification.timeZone = timezone;
notification.alertBody = message;
notification.alertAction = #"Show";
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
}
I use CLLocation * lastLocation = [manager location]; to get the latest location from the device and use this coordinate to see if it is inside the triggered region with containsCoordinate: method. If it is inside, then only the local notification will trigger.
For the details explanation on this bug and the way to fix it, you may visit: iOS Region Monitoring and Location Manager
HERE is full proof working solution/fix for iOS geo-fencing glitch !
It will both solve problem of receiving wrong multiple events on network switch like wifi to mobile data and vice versa..also it gives you accurate results/notifications with this logic/fix
Basically, LocationManager should be taken as singleton and distanceFilter should be kCLDistanceFilterNone and desiredAccuracy should be kCLLocationAccuracyBestForNavigation (We have taken this for best possible accuracy as we need real background monitoring of location very accurate for real time geofence entry notifications to send to users)
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
CLLocation * lastLocation = [manager location];
BOOL doesItContainMyPoint;
if(lastLocation==nil)
doesItContainMyPoint = NO;
else{
CLLocationCoordinate2D theLocationCoordinate = lastLocation.coordinate;
CLCircularRegion * theRegion = (CLCircularRegion*)region;
//we need to take new instance of given region for which the iOS triggers entry event..Adding 50.0 meters is needed just to make sure that containsCoordinate method of CLCircularRegion works well.Because there is lag/difference measured in our real time field testing that brought us to this conclusion and it works like a charm.If we do not add this 50.0 meters in the fence for which we are getting this event then there is a chance that containsCoordinate might miss the recent point/coordinate to consider in given region...
CLCircularRegion * theCircularRegion = [[CLCircularRegion alloc]initWithCenter:theRegion.center radius:theRegion.radius+50.0 identifier:theRegion.identifier];
doesItContainMyPoint = [theCircularRegion containsCoordinate:theLocationCoordinate];
}
if(doesItContainMyPoint){
NSLog(#"ItContainMyPoint");
//trigger local notification...
}else{
NSLog(#"ItDoesNotContainMyPoint");
//do not trigger local notification...because it is triggered due to switching network(wifi to mobile data and vice versa) Currently user is not at all in the region for which we are getting event of entry
return;
}
}
It's an old question, but let my share my experience with Region Monitoring concerning inaccurate didExit- didEnterRegion calls:
One thing to note is that if you have Wifi turned off on the device, the reliability of geofence on iOS devices deteriorates a lot.
In the case of the asker, you should't just check the .coordinate of the last location to debug, but also the .horizontalAccuracy of the CLLocation. That might reveal a very low accuracy (big possible area) if wifi and GPS is turned off. In the case that you also run GPS location tracking, the accepted answer is actually quite a good answer. If not, the .horizontalAccuracy might be a very large number. Region Monitoring does not seem (in my experience) to listen to GPS updates, so you can't enhance its reliability that way. But having WiFi enabled can. In an urban area that is.
Without Wifi and a GPS trick like accepted answer uses, all the device has is cell tower location. I have found that didExitRegion and didEnterRegion may be unreliable if all the device has to get it's location, are cell towers. This is because the accuracy of cell tower location is of course much lower than wifi. In that case, the low accuracy (big possible area) may mean it's in any of the four regions of the asker. It may even be called multiple times for a single region because it may suddenly think (based on cell towers) that it's a kilometer away, then realise it's not, which can cause didEnterRegion to be called multiple times.
The same goes for didExitRegion. If the accuracy is really low, the system cannot be sure you left the region until several kilometers away (which is one of the commenters's problem)
So if you are not sure your users are using your app having wifi always turned on (which you can't check or assure on iOS), make sure you don't make the regions too small or use the accepted answer with GPS ([locationManager startUpdatingLocation]) to ensure that you're really in that region. In that case, also check that the location is accurate and young enough. Something like:
CLLocation * lastLocation = [manager location];
NSTimeInterval locationAge = -[lastLocation.timestamp timeIntervalSinceNow];
if (lastLocation != nil && locationAge < MAX_AGE && self.currentLocation.horizontalAccuracy <= MAX_ACCURACY) {
CLLocationCoordinate2D theLocationCoordinate = lastLocation.coordinate;
CLCircularRegion * theRegion = (CLCircularRegion*)region;
doesItContainMyPoint = [theRegion containsCoordinate:theLocationCoordinate];
}
But if there is any way you can convince the user to always have Wifi enabled when using the app, do!! It makes it so much more reliable.

Can't get CLLocationManager to stop tracking

I have a class that launches an instance of CLLocationManager. The intent is to use it to get a decent, one-time fix on app launch and then stop location services for the duration (or until some other condition is met which requires a new fix...but that part isn't yet written).
For some reason, even though I call [stopUpdatingLocation], my app still seems to be keeping location services active indefinitely, whether in the background or not. My delegate doesn't receive updates anymore, as expected, but the arrow stays on the status bar. I turned off location services for all other apps to verify that mine was the culprit, and then killed my app manually (which immediately dismissed the arrow).
My code is based on what you find in the Apple docs, with some things added for my purposes. I've read through all the pertinent Apple docs and just can't figure out what I'm doing wrong. All the other answers on the subject address people who are using MKMapView and forget to set "showUserLocation" to NO...I'm not using an MKMapView at all, so that's not my issue. What the heck. Why won't it die?
(_locationManager is, of course my instance of CLLocationManager).
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:
(NSArray*)locations
{
CLLocation* lastLocation = [locations lastObject];
// Ignore old (cached) location
NSDate *date = lastLocation.timestamp;
NSTimeInterval howRecent = [date timeIntervalSinceNow];
if (abs(howRecent) > 30.0)
{
DLog(#"Ignoring cached fix");
return;
}
// Wait for better fix if we have GPS
if (lastLocation.horizontalAccuracy > 60 && _GPSEnabled)
{
DLog(#"Ignoring inaccurate fix on GPS-enabled device");
return;
}
// Accept mediocre fix if we don't have GPS
if (lastLocation.horizontalAccuracy < 300 && _GPSEnabled == NO)
{
_hasPos = YES;
_lastPos = lastLocation.coordinate;
DLog(#"Best fix we're likely to get without GPS: %f %f", _lastPos.latitude,
_lastPos.longitude);
[self stopTracking];
return;
}
// If we have GPS, accept a fix with <60m accuracy
_hasPos = YES;
_lastPos = lastLocation.coordinate;
DLog(#"Geolocator has good fix: %f %f", _lastPos.latitude, _lastPos.longitude);
[self stopTracking];
}
-(void)stopTracking
{
DLog(#"Stopped updating locations");
[_locationManager stopUpdatingLocation];
_locationManager.delegate = nil;
}
Finally found the answer in another question...reprinting it here because it took me a while to stumble on it.
I had to call this:
[_locationManager stopMonitoringSignificantLocationChanges];
Even though I never called startMonitoringSignificantLocationChanges in the first place, seems I had to "un-call" it...strange that it works this way, but as soon as I added that line, location services shut down promptly. Hope this helps someone else.

Minimum radius for iOS CLRegion feature of LocatinManager

I´m currently working the the region-feature of the location-manager.
Unfortunately I am unable to get notifications for any border-crossings, which are smaller than 100m.
I created regions with the radius of 20m / 50m or 70m and I always only get a notification, as soon as I cross the 100m-border.
But I would like to have a finer radius - e.g. 20m and also receive a notification for that. Everything works quite well, if I have a range, which is greater than 100m - e.g.
150m. In this case I receive a notification as soon as I enter 150m as I would expect it.
I tried playing around with the "kCLLocationAccuracy"-settings on the LocationManager and the creation of CLRegions, but both does not
seem to have any effect.
This is my code I use:
- (void) initializeLocationManager
{
// Check to ensure location services are enabled
if(![CLLocationManager locationServicesEnabled]) {
[self showAlertWithMessage:#"You need to enable location services to use this app."];
return;
}
if(![CLLocationManager regionMonitoringAvailable]) {
[self showAlertWithMessage:#"This app requires region monitoring features which are unavailable on this device."];
return;
}
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
}
- (void) setupGeoFence:(Station*)station
{
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake([station.gpsPosition.latitude doubleValue], [station.gpsPosition.longitude doubleValue]);
CLRegion *geofence = [[CLRegion alloc] initCircularRegionWithCenter:centerCoordinate radius:[range doubleValue] identifier:station.name];
[self.locationManager startMonitoringForRegion:geofence desiredAccuracy:kCLLocationAccuracyBest];
}
Does anyone have an idea how to receive notification on a closer boundary? Any help would be highly appriciated.
Thanks
Hamtho
Regions at that size are just not really possible. The location events are primarily triggered by the Wifi surrounding the device. GPS isn't really used unless absolutely necessary. So regions under 50M are really a crap shoot. I have spoken with CoreLocation engineers about this (along with some other odd behaviors surrounding region monitoring) and because of the dependency on Wifi, sizes that small are not recommended. They actually recommend 150M, even though it isn't documented.
If you really need location updates that fine grained, you may need to implement your own checks or fire up the GPS to get a very accurate reading. This comes along with a battery hit, so your mileage may vary. Good luck.

Fetch GPS location for every 5 minutes only

In my Location Application implemented didUpdateToLocation method. This method called every second and provides location data. But I dont need to fetch location for every second, I need to fire this method every 5 minutes only. Is it possible to do this?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//initialize location lisetener on Application startup
self.myLocationManager = [[CLLocationManager alloc]init];
self.myLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.myLocationManager.delegate = self;
[self.myLocationManager startUpdatingLocation];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[INNOViewController alloc] initWithNibName:#"INNOViewController_iPhone" bundle:nil];
} else {
self.viewController = [[INNOViewController alloc] initWithNibName:#"INNOViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
/*
if(self.executingInBackground)
{
NSLog(#"Aplication running in background");
}
else
{
NSLog(#"Aplication NOT running in background");
}
*/
//NSLog(#"new location->%# and old location -> %#",newLocation,oldLocation);
NSString *urlAsString = #"http://www.apple.com";
NSURL *url=[NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest=[NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ([data length] > 0 && error == nil) {
NSString *html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Downloaded html -> %#",html);
//NSLog(#"Downloaded successfully");
}
else if([data length] == 0 && error == nil)
{
NSLog(#"Nothing downloaded");
}
else
{
NSLog(#"Error occured -> %#",error);
}
}];
}
It is called that quickly because you asked for kCLLocationAccuracyBest. Back off a bit. It's not based on time, it's based on delta distance. At that accuracy even a small change in distance will trigger an update in an area with good reception. Use a different value.
Again, these methods are not meant to be used based on time. They are meant to be used based on delta distance.
Reduce the accuraccy and the distance filter,this will reduce the frequency in which the method is called
If you want it to be called after 5 minutes then you can forcefully call the methods stopupdating and startupdating every five minutes
You could use startMonitoringSignificantLocationChanges instead of startUpdatingLocation. You would be updated only when user moves around 500 meters from last position
Instead of:
[self.myLocationManager startUpdatingLocation];
use:
[self.myLocationManager startMonitoringSignificantLocationChanges];
If you use: startUpdatingLocation it'll call the delegate method in each second. When you use startMonitoringSignificantLocationChanges it'll call the delegate method when a significant change in location occurs or after 5 minute intervals.
startMonitoringSignificantLocationChanges
Starts the generation of updates based on significant location
changes.
- (void)startMonitoringSignificantLocationChanges
Discussion
This method initiates the delivery of location events asynchronously,
returning shortly after you call it. Location events are delivered to
your delegate’s locationManager:didUpdateLocations: method. The first
event to be delivered is usually the most recently cached location
event (if any) but may be a newer event in some circumstances.
Obtaining a current location fix may take several additional seconds,
so be sure to check the timestamps on the location events in your
delegate method.
After returning a current location fix, the receiver generates update
events only when a significant change in the user’s location is
detected. For example, it might generate a new event when the device
becomes associated with a different cell tower. It does not rely on
the value in the distanceFilter property to generate events. Calling
this method several times in succession does not automatically result
in new events being generated. Calling
stopMonitoringSignificantLocationChanges in between, however, does
cause a new initial event to be sent the next time you call this
method.
If you start this service and your application is subsequently
terminated, the system automatically relaunches the application into
the background if a new event arrives. In such a case, the options
dictionary passed to the locationManager:didUpdateLocations: method of
your application delegate contains the key
UIApplicationLaunchOptionsLocationKey to indicate that your
application was launched because of a location event. Upon relaunch,
you must still configure a location manager object and call this
method to continue receiving location events. When you restart
location services, the current event is delivered to your delegate
immediately. In addition, the location property of your location
manager object is populated with the most recent location object even
before you start location services.
In addition to your delegate object implementing the
locationManager:didUpdateLocations: method, it should also implement
the locationManager:didFailWithError: method to respond to potential
errors.
Note: Apps can expect a notification as soon as the device moves 500
meters or more from its previous notification. It should not expect
notifications more frequently than once every five minutes. If the
device is able to retrieve data from the network, the location manager
is much more likely to deliver notifications in a timely manner.
Declared In CLLocationManager.h
Reference CLLocationManager

Resources