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?
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.
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()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With