My app that worked fine on iOS 7 doesn\'t work with the iOS 8 SDK.
CLLocationManager
doesn\'t return a location, and I don\'t see my app under
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];
}
Setup NSLocationWhenInUseUsageDescription key in your Info.plist
Objective-C Procedure Follow the below instructions:
For iOS-11 For iOS 11 have a look at this Answer: iOS 11 location access
Need to Add two Keys into plist and provide message as below image:
1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
3. NSLocationAlwaysUsageDescription
For iOS-10 and below:
NSLocationWhenInUseUsageDescription
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
[locationManager requestWhenInUseAuthorization];
}else{
[locationManager startUpdatingLocation];
}
Delegate Methods
#pragma mark - Lolcation Update
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"didFailWithError: %@", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
case kCLAuthorizationStatusRestricted:
case kCLAuthorizationStatusDenied:
{
// do some error handling
}
break;
default:{
[locationManager startUpdatingLocation];
}
break;
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
userLatitude = [NSString stringWithFormat:@"%f", location.coordinate.latitude] ;
userLongitude = [NSString stringWithFormat:@"%f",location.coordinate.longitude];
[locationManager stopUpdatingLocation];
}
Swift Procedure
Follow the below instructions:
For iOS-11 For iOS 11 have a look at this Answer: iOS 11 location access
Need to Add two Keys into plist and provide message as below image:
1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
3. NSLocationAlwaysUsageDescription
For iOS-10 and below:
import CoreLocation
class ViewController: UIViewController ,CLLocationManagerDelegate {
var locationManager = CLLocationManager()
//MARK- Update Location
func updateMyLocation(){
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if locationManager.respondsToSelector(#selector(CLLocationManager.requestWhenInUseAuthorization)){
locationManager.requestWhenInUseAuthorization()
}
else{
locationManager.startUpdatingLocation()
}
}
Delegate Methods
//MARK: Location Update
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
NSLog("Error to update location :%@",error)
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .NotDetermined: break
case .Restricted: break
case .Denied:
NSLog("do some error handling")
break
default:
locationManager.startUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last! as CLLocation
var latitude = location.coordinate.latitude
var longitude = location.coordinate.longitude
}
Add key NSLocationWhenInUseUsageDescription
or NSLocationAlwaysUsageDescription
(background GPS use) with string asking to use GPS on each info.plist
from each target.
Ask for permission by running:
[self initLocationManager:locationManager];
Where initLocationManager
is:
// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{
locationManager = [[CLLocationManager alloc]init];
if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
[locationManager requestAlwaysAuthorization];
}
Remember that if the keys are not on each info.plist
for each target the app will not ask the user. The if
provides compatibility with iOS 7 and the respondsToSelector:
method guarantees future compatibility rather than just solving the issue for iOS 7 and 8.
I was working on an app that was upgraded to iOS 8 and location services stopped working. You'll probably get and error in the Debug area like so:
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
I did the least intrusive procedure. First add NSLocationAlwaysUsageDescription
entry to your info.plist:
Notice I didn't fill out the value for this key. This still works, and I'm not concerned because this is a in house app. Also, there is already a title asking to use location services, so I didn't want to do anything redundant.
Next I created a conditional for iOS 8:
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_locationManager requestAlwaysAuthorization];
}
After this the locationManager:didChangeAuthorizationStatus:
method is call:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus: (CLAuthorizationStatus)status
{
[self gotoCurrenLocation];
}
And now everything works fine. As always, check out the documentation.
// ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
// Location Manager Delegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"%@", [locations lastObject]);
}
I add those key in InfoPlist.strings
in iOS 8.4, iPad mini 2. It works too. I don't set any key, like NSLocationWhenInUseUsageDescription
, in my Info.plist
.
InfoPlist.strings:
"NSLocationWhenInUseUsageDescription" = "I need GPS information....";
Base on this thread, it said, as in iOS 7
, can be localized in the InfoPlist.strings. In my test, those keys can be configured directly in the file InfoPlist.strings
.
So the first thing you need to do is to add one or both of the > following keys to your Info.plist file:
- NSLocationWhenInUseUsageDescription
- NSLocationAlwaysUsageDescription
Both of these keys take a string which is a description of why you need location services. You can enter a string like “Location is required to find out where you are” which, as in iOS 7, can be localized in the InfoPlist.strings file.
UPDATE:
I think @IOS's method is better. Add key to Info.plist
with empty value and add localized strings to InfoPlist.strings
.