For iOS SDK 8.0 and later, we need to set NSLocationWhenInUseUsageDescription and ‘NSLocationAlwaysUsageDescription’ in info.plist file. A sample case is:
1 <key>NSLocationWhenInUseUsageDescription</key>
2 <string>Do you allow the app to use your location?</string>
3 <key>NSLocationAlwaysUsageDescription</key>
4 <string>Are you willing to allow the app to use your location?</string>The string will appear in the popup dialog. You can leave it as empty, and only the system message will appear in the popup.
We ask for the authorization by an instance of CLLocationManager.
CoreLocation/CoreLocation.h class, and define a location manager locationManager in the map view controller. 1 if ([CLLocationManager locationServicesEnabled] ) { // check if the location service is enabled for the device
2 if (self.locationManager == nil ) {
3 self.locationManager = [[CLLocationManager alloc] init];
4 self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
5 self.locationManager.distanceFilter = kCLDistanceFilterNone;
6 }
7 // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
8 if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
9 CLAuthorizationStatus locationAuthorizationStatus = [CLLocationManager authorizationStatus];
10 if (locationAuthorizationStatus == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
11 // choose one request according to your business.
12 if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
13 [self.locationManager requestAlwaysAuthorization];
14 } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
15 [self.locationManager requestWhenInUseAuthorization];
16 } else {
17 NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
18 }
19 }
20 }
21 }For iOS SDK 8.0 and later, we have two ways to get user current location:
showsUserLocation to YES for map view.startUpdatingLocation to CLLocationManager instance.For this way, after we set showsUserLocation to YES,
mapView:didUpdateUserLocation:. 1 - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
2 {
3 // Center the map the first time we get a real location change.
4 static dispatch_once_t centerMapFirstTime;
5
6 if ((userLocation.coordinate.latitude != 0.0) && (userLocation.coordinate.longitude != 0.0)) {
7 dispatch_once(¢erMapFirstTime, ^{
8 [self.mapView setCenterCoordinate:userLocation.coordinate animated:YES];
9 });
10 }
11
12 }mapView:viewForAnnotation:. If nil is returned, a default blue circle with white boundary is use. The circle has breathing effect. For this purpose, we need to identify the annotation (which is an id type) type: if it is a MKUserLocation type, return a current location annotation view or nil. Question: How to define whether an id type object is a MKUserLocation type object?Before implementing the above two methods, we should set the map view’s delegate comfirm with MapViewDelegate protoco.
startUpdateingLocation to CLLocationManager InstaanceFor this way, after we send the method,
locationManager:didUpdateLocations:. The newest location is the lastObject of locations. 1 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
2 {
3 self.currentLocation = [locations lastObject];
4 CLLocationCoordinate2D currentCoordinate = self.currentLocation.coordinate;
5
6 if (self.currentLocationAnnotation) {
7 [self.mapView removeAnnotation:self.currentLocationAnnotation];
8 }
9 self.currentLocationAnnotation = [[CurrentLocationAnnotation alloc] initWithCoordinate:currentCoordinate];
10 [self.mapView addAnnotation:self.currentLocationAnnotation];
11 }When you add the current location annotation to map view, you can set the current location annotation view in mapView:viewForAnnotation: method. If nil is returned, a red pin will be use as the annotation view. Question: How can we use the default blue circle as the annotation view, just as we set showsUserLocation to YES?
You can also get erroe message when app fails to get the location in locationManager:didFailWithError: method.
1 - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
2 {
3 NSLog(@"didFailWithError: %@", error);
4 UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
5 [errorAlert show];
6 }Before implementing the above methods, set the CLLocationManager’s delegate confirm with CLLocationManagerDelegate protoco.