Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: App is not asking user's permission while installing the app. getting kCLAuthorizationStatusNotDetermined every time - Objective-c & Swift

I am trying to fetch user location in my iOS app. I have included corelocation framework in my project first. Then on a button click I am invoking the core location api as below. When I am trying to install this in a device, the core location never asks the user permission. When I try to fetch the location on button click, I am getting kCLAuthorizationStatusNotDetermined as the authorisationStatus. Please help me in this. I have no clue what is happening.

- (IBAction)fetchLessAccurateLocation:(id)sender {     [self.txtLocation setText:@""];      locationManager = [[CLLocationManager alloc] init];     locationManager.delegate = self;     locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;     locationManager.distanceFilter = 1000;      if ([self shouldFetchUserLocation]) {         [locationManager startUpdatingLocation];     } } 

This is my shouldFetchUserLocation method:

-(BOOL)shouldFetchUserLocation{      BOOL shouldFetchLocation= NO;      if ([CLLocationManager locationServicesEnabled]) {         switch ([CLLocationManager authorizationStatus]) {             case kCLAuthorizationStatusAuthorized:                 shouldFetchLocation= YES;                 break;             case kCLAuthorizationStatusDenied:             {                 UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"App level settings has been denied" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];                 [alert show];                 alert= nil;             }                 break;             case kCLAuthorizationStatusNotDetermined:             {                 UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The user is yet to provide the permission" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];                 [alert show];                 alert= nil;             }                 break;             case kCLAuthorizationStatusRestricted:             {                 UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The app is recstricted from using location services." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];                 [alert show];                 alert= nil;             }                 break;              default:                 break;         }     }     else{         UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The location services seems to be disabled from the settings." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];         [alert show];         alert= nil;     }      return shouldFetchLocation; } 

Here is my core location delegate method:

- (void)locationManager:(CLLocationManager *)manager     didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0){      NSLog(@"location fetched in delegate");      CLLocation* location = [locations lastObject];     NSDate* eventDate = location.timestamp;     NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];      if (abs(howRecent) < 15.0) {         // If the event is recent, do something with it.         NSLog(@"inside loop.... latitude %+.6f, longitude %+.6f\n",               location.coordinate.latitude,               location.coordinate.longitude);     }     NSLog(@"latitude %+.6f, longitude %+.6f\n",           location.coordinate.latitude,           location.coordinate.longitude);     [self.txtLocation setText:[NSString stringWithFormat:@"\nlatitude: %+.6f \nlongitude:   %+.6f", location.coordinate.latitude, location.coordinate.longitude]];      [locationManager stopUpdatingLocation];     [locationManager stopMonitoringSignificantLocationChanges];      if(locationManager!=nil){         locationManager.delegate= nil;         locationManager= nil;     } } 
like image 241
Rashmi Ranjan mallick Avatar asked Dec 18 '13 17:12

Rashmi Ranjan mallick


2 Answers

iOS8 has got us major API changes with the LocationsServices

Assuming [CLLocationManager locationServicesEnabled] return YES,

With the First Launch of the iOS App [both iOS7 and iOS8] - locationMangers(CLLocationManager) authorizationStatus preset to

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined 

Prompting in iOS7+

Initiate the locationManger (CLLocationManager , Strong) and set the delegates(CLLocationManagerDelegate)

Now to prompt the user to use Locations Services and List the App under the Settings> Privacy> Locations Services its MUST to call any of the Locations Services Methods, its depends on the App requirement- for example if app is kind of one of the below

Locations Updates - [self.locationManager startUpdatingLocation]

RegionMonitoring - [self.locationManager startMonitoringForRegion:beaconRegion]

right after executions of the above method iOS will prompt user requesting to accept use of Locations Services in app and irrespective of user choice app will be listed under the Settings > Privacy > Locations Services.

Prompting in iOS8+

Its in same case with iOS8, with the first launch the App Locations Services

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined 

iOS 8 we got new methods for showing prompt to user

[self.locationManager requestAlwaysAuthorization]  or [self.locationManager requestWhenInUseAuthorization] 

requestAlwaysAuthorization/requestWhenInUseAuthorization availbable from iOS8. if App deployment target is iOS7 then wrap this under if block to make sure in iOS7 this doesn't lead to app crash.

if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { [self.locationManager requestAlwaysAuthorization]; . } 

or

if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { [self.locationManager requestWhenInUseAuthorization]; } 

Very Important ###:

As per iOS8 its mandatory to include the string stating why app uses requestAlwaysAuthorization/requestWhenInUseAuthorization In info.plist include any of these property respective to the requirement of the app

for kCLAuthorizationStatusAuthorizedAlways include Key/Value(string Value) pair

NSLocationAlwaysUsageDescription = App use Locations service mode Always 

for kCLAuthorizationStatusAuthorizedWhenInUse include Key/Value(string Value) pair

NSLocationWhenInUseUsageDescription = App use Locations service mode In Use  

Screenshot of info.plist (in case anybody is confused by this) enter image description here

like image 198
Rithesh Rao Avatar answered Sep 22 '22 21:09

Rithesh Rao


I was facing the same issue, after re-installing my app it was returning kCLAuthorizationStatusNotDetermined whenever checking for [CLLocationManager authorizationStatus] and the app didn't even show up in Settings > Privacy > Location Services.

The authorization dialog that iOS prompts user to approve access to location services is triggered on [locationManager startUpdatingLocation] which in your case is never called (shouldFetchUserLocation will be always NO).

Miguel C.'s solution seems like a good fix, will try that.

Edit for iOS8.x

When iOS8 came it brought little change in the way CLLocationManager is used. As mentioned few times in other answers it requires additional step comparing to iOS7. Today I faced the issue myself and found this article (it's been referenced from multiple other questions but it completes my earlier answer). Hope it helps!

like image 32
David Jirman Avatar answered Sep 21 '22 21:09

David Jirman