7

UPDATE: THIS IS NOT A DUPLICATE. I have already added the required key to the info.plist as stated in my original question and the issue remains. I have tried all three keys in various combinations.

Before anyone gets upset, I have read through many Apple Dev forum posts and stack overflow posts and cannot figure out why my app refuses to prompt the user to allow When In Use authorization.

I've added the following key to my Info.plist file with an accompanying String value:

NSLocationWhenInUseUsageDescription

I've then written (both in Swift and Obj-C) the code that should prompt the user:

@property CLLocationManager *location;
...
@synthesize location;
...
location = [[CLLocationManager alloc] init];
location.delegate = self;

location.desiredAccuracy = kCLLocationAccuracyBest;
location.distanceFilter = kCLDistanceFilterNone;

[location requestWhenInUseAuthorization];
[location startUpdatingLocation];


I'm using the following CLLocationManagerDelegate methods.
- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
- (void) locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status

This was basically copied straight from the Apple "LocateMe" sample code.

No matter what various sequences or minor changes I try, the app never prompts to allow authorization. I've used a switch statement to determine the state of [CLLocationManager authorizationStatus], but continually recieve a "Not Determined" response.

if ([CLLocationManager locationServicesEnabled]) {
        switch ([CLLocationManager authorizationStatus]) {
            case kCLAuthorizationStatusAuthorizedAlways:
                NSLog(@"Always Authorized");
                break;
            case kCLAuthorizationStatusDenied:
                NSLog(@"Denied");
                break;
            case kCLAuthorizationStatusAuthorizedWhenInUse:
                NSLog(@"Authorized in Use");
                break;
            case kCLAuthorizationStatusNotDetermined:
                NSLog(@"Not Determined");
                break;
            case kCLAuthorizationStatusRestricted:
                NSLog(@"Restricted");
                break;
        }

    }

Any help would be greatly appreciated. I'm running Xcode 6.2 (6C101) with iOS 8.1.2 physical device and iOS 8.2 (12D5452a) simulator for testing.

Andrew
  • 968
  • 2
  • 11
  • 22
  • @n00bProgrammer I don't see that reset option available in the Settings > Reset tab of the simulator. Also, I've written two programs, one in Swift and one in Obj-C and both do the same thing. I've also tested with a physical device and got the same results. I've not tried resetting the hardware yet. – Andrew Dec 29 '14 at 18:25

5 Answers5

3

If you have changed the Location Settings in your iPhone simulator this may cause the prompt to not show. For example, if you are already set the Location permissions via Allow Locations access iOS prompt and made a decision this is stored in the Privacy settings for the iPhone simulator and so subsequent calls to locationManager.requestAlwaysAuthorization() or locationManager.requestWhenInUseAuthorization() will not display the iOS prompt because you already have defined your Privacy -> Location Settings for your app.

To clear settings for an iPhone simulator: "iOS Simulator" -> "Reset Content and Settings..."

Also I did a Clean build in Xcode and quit and restarted the iPhone simulator at some point, I could be wrong about this part being of any help...

Brian Ogden
  • 18,439
  • 10
  • 97
  • 176
2

I faced the exact same problem, after digging in for two days, it turned out that the app does not read from the info.plist file that is included in the bundle in project navigator's pane, because it has been localized to another language and base internationalization is being used, that means in Finder there will be 3 info.plist files:

1- under Tests folder

2- under base.lproj folder

3- under ar.lprj (ar refers to Arabic language).

the project reads from base.lproj's version which is not included inside the bundle in the project navigator's pane.

what I did is that I took a backup copy of the plist file that I want (number 2 above), and removed localization on the info.plist file that is inside project navigator and chose delete from disk to delete it completely, then I took the back up copy and placed in under project's root in Finder and import it back in Xcode, and now the project reads from the new info.plist file and the key NSLocationWhenInUseUsageDescription fires up the user authorization alert at app launch.

hope this helps.

JAHelia
  • 6,934
  • 17
  • 74
  • 134
1

I found that in your info.plst file you can't use the Privacy - Location Usage Description key, you have to have a key called NSLocationWhenInUseUsageDescription and a value. I was able to get your code working by adding this key into my info.plist

enter image description here

#import <MapKit/MapKit.h>

@interface ViewController ()

@property CLLocationManager * location;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _location = [[CLLocationManager alloc] init];

    self.location.delegate = self;
    self.location.desiredAccuracy = kCLLocationAccuracyBest;
    self.location.distanceFilter = kCLDistanceFilterNone;

    [_location requestWhenInUseAuthorization];
    [self.location startUpdatingLocation];
}
ecnepsnai
  • 1,882
  • 4
  • 28
  • 56
  • However I'm testing on 8.1, not 8.2. – ecnepsnai Dec 29 '14 at 18:56
  • I've tested this using the three different keys available in various ways hoping to get it to work -- at one point, one of my projects magically started working, but I can't replicate those changes to this simple project (who's sole purpose is this test) to make it prompt. – Andrew Dec 29 '14 at 20:56
1

Lots of useful comparisons here: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

Also, silly question time: you mix _location and self.location but you don't show your property/synthesize code. Are you sure you're operating on the same object?

Brad Brighton
  • 2,179
  • 1
  • 13
  • 15
  • I edited the code to add the @synthesize and modify the property to simply use the value `location`. Also. I have read this page, but it doesn't help my issue for some reason. The `NSLocationWhenInUseUsageDescription` is a String value in my Info.plist file. – Andrew Dec 29 '14 at 20:55
  • Here is a snip from an active project of mine that prompts correctly. Except for the iOS7/8 compatibility test, it basically matches yours. ` _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { [_locationManager requestWhenInUseAuthorization]; } [_locationManager startUpdatingLocation]; ` Huh. GuessMode: Check Settings>Privacy>Location Services. Are there any settings for your app already? – Brad Brighton Dec 29 '14 at 21:56
  • No settings shown and the CLAuthorization status is `Not Determined` – Andrew Dec 29 '14 at 22:02
  • 1
    "Not Determined" is correct. That's where the prompt _should_ be happening (as you're aware). Does "no settings shown" mean your app is not in the list or that your app _is_ in the list but nothing is checked for permission? If it's the former, I'd say it's probably time to nuke all the built assets (app on the device/sim, project caches, derived data, etc) clean and rebuild. If it's the latter, there's still no guarantee, but that's exactly the symptom I ran into when the new plist entries weren't correct in my own code. – Brad Brighton Dec 29 '14 at 22:09
  • You may also find it useful to check into this Apple sample code: https://developer.apple.com/library/ios/samplecode/PrivacyPrompts/Introduction/Intro.html which I will note FAILS out of the box in iOS 8. Add: ` if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { [self.locationManager requestWhenInUseAuthorization]; }` to -requestLocationServicesAuthorization and add the NSLocationWhenInUseUsageDescription string to the plist and it will prompt when it hasn't already successfully prompted. You can use this to narrow your blocker further. – Brad Brighton Dec 29 '14 at 22:29
  • You're right in that the latter is the issue -- the app is registered as using Location Services, but doesn't have an option selected. I'll try cleaning everything one more time, maybe even build a new test app from scratch just to double check. Thanks for the help so far! – Andrew Dec 30 '14 at 01:55
0

It may be silly, but i just spent almost 2 hours double and triple checking all of the answers i could find about CLLocationManager permissions.

I felt stupid when i finally realized that i had 2 info.plist files and i was using the wrong one!

You can check in your project's build settings - there's a value called Info.plist File.

Just want to leave it here for future readers.

chents
  • 393
  • 3
  • 14