To get a location in iOS device, there are areas that we need to think about before we implement / design for getting location in an application.
Points / Areas to consider:
- Where to register in application for getting location updates
- Accuracy – What accuracy of location are we looking for
- Exit Strategy in case no location provided
- Check whether location services are enable / disable on the device
- Check permissions to get location
- Fall-back strategy – If we don’t get the location
- Where to de-register in application for getting location updates
1. Where to register in application for getting location updates
In case we need location at the time of application launch, we need to register the LocationManger to our application, We need to do that in AppDelegate and method is:
– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self registerForLocationUpdates]; return YES; } //Register User Location -(void) registerForLocationUpdates { LocationManager *locManager = [LocationManager getInstance]; [locManager setManager]; [locManager registerForLocation]; }
2. Accuracy – What accuracy of location are we looking for
Location accuracy requirement might vary. If application wants to know which city the user is into at the moment then low accuracy will also work. If the application is providing some navigation information then it has to have high accuracy location.
Upon creating the LocationManager instance we need to set the ‘desiredAccuracy’. There are five accuracy parameters we can set
kCLLocationAccuracyBest (Best accuracy)
kCLLocationAccuracyNearestTenMeters
kCLLocationAccuracyHundredMeters
kCLLocationAccuracyKilometer
kCLLocationAccuracyThreeKilometers
For kCLLocationAccuracyBest – Source of location – GPS and Power consumption is High
For kCLLocationAccuracyThreeKilometers – Source of location – Network and Power consumption is Low
Situation – If we give Best Accuracy and it did not get from GPS then it will not get it from Network. It will give call back ‘didFailWithError’.
3. Exit Strategy in case no location provided.
It is possible that application has registered for getting location and it is taking time to get the location update. We need to think of a strategy for exit from the current way of getting location. One way could be that we start a timer when we register to get location and if no location is obtained before timer finishes then we stop for getting location update and go to a Fall-back Strategy (See below).
4. Check whether location services are enable / disable on the device.
Before starting to register for location updates, firstly we need to check whether location services is ON or OFF.
To check the location service status:
-(BOOL) isLocationServicesEnabled { if([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] != kCLAuthorizationStatusDenied) { return YES; // show the map } else { return NO; // show error } }
5. Check permissions to get location
To access location of the device, app needs to prompt the user to get permission from the user to access location. It is possible that user might have not given the permission to the app.
We need to handle this situation and prompt the user giving a proper message.
6. Fall-back strategy – If we don’t get the location
If we don’t get location then what should the application do. It depends on the situation in the application.
Ex – We can show a pre-defied list of places (Countries, Cities) and let the user choose from it
Or
Don’t allow the user to enter the application
Or
Let user go inside the application and use those parts of the app that are not dependent on location
7. Where to de-register in application for getting location updates
Once we have the location or failed to get the location then we need to de-register the application.
Code snippet trying to cover the above points:
#import "LocationManager.h" @implementation LocationManager @synthesize locationManager; static LocationManager *sharedInstance = nil; #pragma mark LocationMannager singleton class method + (LocationManager *) getInstance { @synchronized(self) { if(sharedInstance == nil) { sharedInstance = [[self alloc] init]; } } return sharedInstance; } -(void) setManager { self.locationManager = [[CLLocationManager alloc]init]; self.locationManager.delegate = self; self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; NSUInteger code = [CLLocationManager authorizationStatus]; if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) { // choose one request according to your business. if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) { [self.locationManager requestAlwaysAuthorization]; } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) { [self.locationManager requestWhenInUseAuthorization]; } else { NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription"); } } } -(void) registerForLocation { [self.locationManager startUpdatingLocation]; // [self.pLocationManager startMonitoringSignificantLocationChanges]; } -(void) unRegisterForLocation { [self.locationManager stopUpdatingLocation]; // [self.pLocationManager stopMonitoringSignificantLocationChanges]; } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { BOOL is =[CLLocationManager locationServicesEnabled]; if(is) { CLLocation* location = [locations lastObject]; // NSLog(@"Tracking from singlton %f %f %@ ",location.coordinate.latitude,location.coordinate.longitude,[NSDate date]); } } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"Unable to update with error %@ ",[error localizedDescription]); self.locationManager = nil; } -(BOOL) isLocationServicesEnabled { if([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] != kCLAuthorizationStatusDenied) { return YES; // show the map } else { return NO; // show error } } @end