Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CLLocationManager authorization issue iOS 8

I am working on a piece of Swift code for iOS 8. I am trying to do something which involves location, and so i have implemented the following in my swift view controller file:

let locationManger:CLLocationManager = CLLocationManager()

var speedReceived:Double = 0

override func viewDidLoad() {
    super.viewDidLoad()
    locationManger.delegate = self
    locationManger.desiredAccuracy = kCLLocationAccuracyBest
    let authstate = CLLocationManager.authorizationStatus()
    if(authstate == CLAuthorizationStatus.NotDetermined){
       println("Not Authorised")  
      locationManger.requestWhenInUseAuthorization()
    }
    // Do any additional setup after loading the view, typically from a nib.
}

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
    var location:CLLocation = locations[locations.count - 1] as CLLocation
    if(location.horizontalAccuracy > 0){
        self.speedReceived = location.speed
        println(self.speedReceived)
    }
}

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
   println("Couldn't get your location")
}

However, I can't seem to get this code to work. It doesn't save my preference for location use. it doesn't even prompt me to give permit to access location. I have tried updating my info.plist. But it's not working. Btw, if i select always in the privacy settings within the simulator, it works if i switch back to the app immediately. can anyone help? I am sure that that's the problem because i get Not Authorised on my console.

Any help?

like image 639
brisi123 Avatar asked Jul 10 '14 06:07

brisi123


6 Answers

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.

like image 152
Alex Peda Avatar answered Nov 15 '22 16:11

Alex Peda


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.

like image 7
Cole Richards Avatar answered Nov 15 '22 17:11

Cole Richards


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

like image 4
hrchen Avatar answered Nov 15 '22 16:11

hrchen


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.

like image 2
Chris Marshall Avatar answered Nov 15 '22 16:11

Chris Marshall


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

enter image description here

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>
like image 2
Vincent Avatar answered Nov 15 '22 15:11

Vincent


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()
}
like image 1
Carl Avatar answered Nov 15 '22 17:11

Carl