CLLocationManager authorization issue iOS 8

笑着哭i 提交于 2019-11-28 08:22:10

It's an iOS 8 related issue. You have to put NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription keys in your .plist file (value may be an additional message that will be presented in location alert). These keys are required in iOS 8.

How it's said in Apple guidelines:

This key is required when you use the requestAlwaysAuthorization method of the CLLocationManager class to request authorization for location services. If this key is not present and you call the requestAlwaysAuthorization method, the system ignores your request and prevents your app from using location services.

I had struggled with a similar issue, which persisted even after adding the NSLocationAlwaysUsageDescription/NSLocationWhenInUseUsageDescription keys to the plist.

Eventually, I added the "Privacy - Location Usage Description" key to the plist (in addition to the new keys) and voila, it worked! After it worked once I was able to remove the "Privacy - Location Usage Description" key from the plist and continue to successfully request authorization.

iOS 8 has changed location authorization strategy. Solution with backward compatibility:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}

Reminder: setup NSLocationWhenInUseUsageDescription key in your Info.plist

I had the exact same issue.

For the record, this is not the official answer. The first answer is the correct one. I just wanted to add a link to a FOSS (Objective-C) project that illustrates the fix.

As noted, I had to add the key. My app does not need to run in the background, so I added the NSLocationWhenInUseUsageDescription key to my info.plist.

If you add a string as the value for this key (optional -the existence of the key is enough to set the bar), then that string will appear in the authorization popup.

I then added the following code before all my [CLLocationManager startUpdating] calls:

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

The respondsToSelector is important, as the call is only available in iOS 8.

The first time this is called, the alert is shown. After that, it falls through.

Note that I call requestWhenInUseAuthorization

It has to match the value I put in the plist. I guess you could put both, but I dunno. I didn't need to.

The project is here. Most of the work (not much) is in the BMLTAppDelegate.m file.

This is a nasty surprise. Lots of folks have no idea that their apps will stop working in iOS 8. They'll do the same thing I initially did: Give it a quick run in the simulator, note the hang, and chalk it up to a beta bug.

Now, I have a different problem: All my apps are fixed, but Xcode crashes when I try to upload the apps to the App Store. I have a RADAR open on it.

Xcode 6 is kinda creaky. I expect a patch to come out pretty quickly.

Vincent

Since I do not like to edit the plist directly, I always grant autorisation by using the UI.

The Dutch texts "Toegang is nodig" and "Toegang is noodzakelijk" are displayed in the PopUp in which the used grants access. You can change these to any text you like.

Simply add to plist source,

<key>NSLocationAlwaysUsageDescription</key>
<string>To get location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>To get location</string>

For Swift 2 I've replaced the respondsToSelector() check with an iOS version check. Not as elegant but it's required for Xcode 7 to give 0 errors, 0 warnings

if #available(iOS 8.0, *) {
    locationManager.requestWhenInUseAuthorization()
} else {
    locationManager.startUpdatingLocation()
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!