ChatGPT解决这个技术问题 Extra ChatGPT

Location Services not working in iOS 8

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 Settings -> Location Services either. I did a Google search on the issue, but nothing came up. What could be wrong?

You can also use this as reference app for the solution github.com/jbanford/ConstantLocationUpdates
I posted about some of the changes to the location manager in iOS 8 here: nevan.net/2014/09/core-location-manager-changes-in-ios-8
You could try using this library which simplifies the Core Location APIs and exposes a nice blocks based interface, and normalises all the differences between different iOS versions (Full disclosure: I'm the author): github.com/lmirosevic/GBLocation
I found some reference here datacalculation.blogspot.in/2014/11/…
@nevanking You sir! need a crown! I have been fighting with this problem since change and have yet to find an "guide" how to fix it, that was noob friendly.. Your guide made an idiot like me, handle the problem my self. Thank you so much for that link.

J
Jean-François Fabre

I ended up solving my own problem.

Apparently in iOS 8 SDK, requestAlwaysAuthorization (for background location) or requestWhenInUseAuthorization (location only when foreground) call on CLLocationManager is needed before starting location updates.

There also needs to be NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in Info.plist with a message to be displayed in the prompt. Adding these solved my problem.

https://i.stack.imgur.com/iuOzB.jpg

For more extensive information, have a look at: Core-Location-Manager-Changes-in-ios-8


can you share the exact valur u updated in Info.plist? Iam not able to see that key in my Info.plist. I added it and still it does not seem to work. I am using Swift, iOS8 and XCode 6 beta 4
@Vjay - you have to edit the Info.plist file in an editor, cannot set those keys in Xcode (as of beta 6).
Just a reminder, if you don't wanna show custom explanation to the user, just set this key to an empty string.
You need to retain your locationManager to make it work. so make your CLLocationManager as a strong property
I 'LOVE' that you get no error, no warning, no log message, NOTHING if you leave out the plist entry. Basically Apple has created an API call that does NOTHING if you don't have the appropriate plist entry. Thanks to @OrtwinGentz for figuring this out.
U
User1

I was pulling my hair out with the same problem. Xcode gives you the error:

Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.

But even if you implement one of the above methods, it won't prompt the user unless there is an entry in the info.plist for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription.

Add the following lines to your info.plist where the string values represent the reason you you need to access the users location

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>

I think these entries may have been missing since I started this project in Xcode 5. I'm guessing Xcode 6 might add default entries for these keys but have not confirmed.

You can find more information on these two Settings here


xcode 6 does not add these keys by default, if you intend to implement CLLocationManager you must add them manually
I also had to add these manually, could not add through the RawValues view of info.plist in Xcode6!
i looked forever for this. My [CLLLocationManager authorizationStatus] message was only returning a value of . After adding the above keys it started returning the respective enumerations for the messages' output. From what ive found this is a known iOS 8 bug but couldnt find anything in my context for ages. Thanks a mil!
I like the string value you put in
The message will appear as the sub-message in the Alert that asks whether the user would like to share their location. As such, simply being empty (blank) seems to make the most sense in my application. An explanation of why you want to use location would also make sense. However, NSLocationWhenInUseUsageDescription did not behave as expected for me (ie. kept getting permission denied, even though the return value was correct). NSLocationAlwaysUsageDescription worked fine.
J
JKo

To ensure that this is backwards compatible with iOS 7, you should check whether the user is running iOS 8 or iOS 7. For example:

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

//In ViewDidLoad
if(IS_OS_8_OR_LATER) {
   [self.locationManager requestAlwaysAuthorization];
}

[self.locationManager startUpdatingLocation];

A better way than checking version is to check to see if the object has that selector, e.g.: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
I had trouble just implementing @progrmr's solution when building on Xcode 5, since it doesn't know what the requestAlwaysAuthorization method is. My additional solution was to use this line in the if statement instead of a normal method call: [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. Maybe this is obvious to other people, but it took me a while to figure out. I think it's the right solution until the final Xcode 6 is released.
The right solution is to build with Xcode 6. If you are building with Xcode 5 you don't need to request authorization, it's automatic.
You might have a point. My concern was that I wanted my code to compile in Xcode 5 (even though it won't work on iOS 8 unless compiled in Xcode 6) while my team transitions to Xcode 6. But maybe it's a better workflow to write the code normally and not merge it in until we move to Xcode 6.. Thanks.
@VinceFior the recommended approach is to conditionally compile using the SDK defined macro __IPHONE_OS_VERSION_MAX_ALLOWED (#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
A
Alex Zavatone
- (void)startLocationManager
{
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
    [locationManager requestWhenInUseAuthorization]; // Add This Line


}

https://i.stack.imgur.com/bQcRQ.png


Found similar solution in more descriptive way at datacalculation.blogspot.in/2014/11/…
@Hemang: According to the Apple Dev Documentation: It is safe to start location services before the authorization status of your app is determined. Although you can start location services, those services do not deliver any data until the authorization status changes to kCLAuthorizationStatusAuthorizedAlways or kCLAuthorizationStatusAuthorizedWhenInUse.
A bit late, but I recommend You hide irrelevant parts of Your plist file, especially FacebookAppID
Thanks But thats just a dummy sample :)
It's also important that the project is pointing to the right info.plist (the one where the key is defined). That's determined in the project build settings under Info.plist File.
C
Cœur

According to the Apple docs:

https://developer.apple.com/documentation/corelocation/requesting_permission_to_use_location_services

https://developer.apple.com/documentation/corelocation/cllocationmanager/1620562-requestwheninuseauthorization

As of iOS 8, the presence of a NSLocationWhenInUseUsageDescription or a NSLocationAlwaysUsageDescription key value in your app's Info.plist file is required. It's then also necessary to request permission from the user prior to registering for location updates, either by calling [self.myLocationManager requestWhenInUseAuthorization] or [self.myLocationManager requestAlwaysAuthorization] depending on your need. The string you entered into the Info.plist will then be displayed in the ensuing dialog.

If the user grants permission, it's business as usual. If they deny permission, then the delegate is not informed of location updates.


I found simple description here at datacalculation.blogspot.in/2014/11/…
C
Community
- (void)viewDidLoad
{
    
    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc] init];
    
    self.locationManager.delegate = self;
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
        NSUInteger code = [CLLocationManager authorizationStatus];
        if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
            // choose one request according to your business.
            if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
                [self.locationManager requestAlwaysAuthorization];
            } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
                [self.locationManager  requestWhenInUseAuthorization];
            } else {
                NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
            }
        }
    }
    [self.locationManager startUpdatingLocation];
}

>  #pragma mark - CLLocationManagerDelegate

    - (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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        NSLog(@"didUpdateToLocation: %@", newLocation);
        CLLocation *currentLocation = newLocation;
        
        if (currentLocation != nil) {
            longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
            latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
        }
    }

In iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start. There are two Info.plist keys for the new location authorization. One or both of these keys is required. If neither of the keys are there, you can call startUpdatingLocation but the location manager won’t actually start. It won’t send a failure message to the delegate either (since it never started, it can’t fail). It will also fail if you add one or both of the keys but forget to explicitly request authorization. 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.

https://i.stack.imgur.com/aQuZf.png


P
Peter Mortensen

My solution which can be compiled in Xcode 5:

#ifdef __IPHONE_8_0
    NSUInteger code = [CLLocationManager authorizationStatus];
    if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
        // choose one request according to your business.
        if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
            [self.locationManager requestAlwaysAuthorization];
        } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
            [self.locationManager  requestWhenInUseAuthorization];
        } else {
            NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
        }
    }
#endif
    [self.locationManager startUpdatingLocation];

Nice dynamic solution, to use in all apps. I would change the order though and instead of checking for iphone 8.0, I would check if location manager responds to authorization and then run the authorizationstatus to get the code. This will make it more universal.
Worked on xCode 7.2 as well.
P
Peter Mortensen

The old code for asking location won't work in iOS 8. You can try this method for location authorization:

- (void)requestAlwaysAuthorization
{
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    // If the status is denied or only granted for when in use, display an alert
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status ==        kCLAuthorizationStatusDenied) {
        NSString *title;
        title = (status == kCLAuthorizationStatusDenied) ? @"Location services are off" :   @"Background location is not enabled";
        NSString *message = @"To use background location you must turn on 'Always' in the Location Services Settings";

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
                                                            message:message
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];
        [alertView show];
    }
    // The user has not enabled any location services. Request background authorization.
    else if (status == kCLAuthorizationStatusNotDetermined) {
        [self.locationManager requestAlwaysAuthorization];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        // Send the user to the Settings for this app
        NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:settingsURL];
    }
}

UIAlertView has been deprecated. You should use UIAlertController instead.
yeah I know its deprecated but this will also work. but yes better use UIAlertController for IOS8.
b
byJeevan

In iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start

info.plist:

<key>NSLocationUsageDescription</key>
<string>I need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need location</string>

Add this to your code

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

it's not clear if your pseudocode is a preprocessor call or a regular call
Add this to your constants.h or .pch file: #define IS_OS_8_OR_LATER ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)
Why would you request both, you should add a comment mentioning only to use one or the other depending on your application needs
the info.plist part is easy enough to do in Unity3d, but how would I add the code part if using unity3d ? where ?
s
st.derrick

One common error for Swift developers:

First make sure you add a value to the plist for either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription.

If you are still not seeing a window pop up asking for authorization, look to see if you are putting the line var locationManager = CLLocationManager() in your View Controller's viewDidLoad method. If you do, then even if you call locationManager.requestWhenInUseAuthorization(), nothing will show up. This is because after viewDidLoad executes, the locationManager variable is deallocated (cleared out).

The solution is to locate the line var locationManager = CLLocationManager() at the top of the class method.


P
Peter Mortensen

Before [locationManager startUpdatingLocation];, add an iOS8 location services request:

if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    [locationManager requestAlwaysAuthorization];

Edit your app's Info.plist and add key NSLocationAlwaysUsageDescription with the string value that will be displayed to the user (for example, We do our best to preserve your battery life.)

If your app needs location services only while the app is open, replace:

requestAlwaysAuthorization with requestWhenInUseAuthorization and

NSLocationAlwaysUsageDescription with NSLocationWhenInUseUsageDescription.


P
Peter Mortensen

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:

https://i.stack.imgur.com/N4M21.png

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.


h
hrchen

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


This is not correct, what about the case kCLAuthorizationStatusDenied? it jumps to else and starts updating the location which is not correct!
@BenMarten I don't think it should matter. You should be handling that yourself with locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error. He did, however, forget to add startUpdatingLocation to the if statement so after they accept or deny it, it doesn't actually call startUpdateLocation.
b
byJeevan

Solution with backward compatibility which doesn't produce Xcode warnings:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
  [self.locationManager respondsToSelector:requestSelector]) {
((void (*)(id, SEL))[self.locationManager methodForSelector:requestSelector])(self.locationManager, requestSelector);
  [self.locationManager startUpdatingLocation];
} else {
  [self.locationManager startUpdatingLocation];
}

Setup NSLocationWhenInUseUsageDescription key in your Info.plist.

For iOS version 11.0+ : Setup NSLocationAlwaysAndWhenInUseUsageDescription key in your Info.plist. along with other 2 keys.


This is not correct, what about the case kCLAuthorizationStatusDenied? it jumps to else and starts updating the location which is not correct!
This is quite strange, this works fine for me not fine perfectly fine with both allow and not allowing.Even Jacob solution looks accurate but didn't work for me. Strange but worked!!!
Calling [self.locationManager startUpdatingLocation] right after requestWhenInUseAuthorization has no point
P
Pooja Patel

This is issue with ios 8 Add this to your code

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

and to info.plist:

 <key>NSLocationUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationAlwaysUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationWhenInUseUsageDescription</key>
 <string>I need location</string>

NSLocationUsageDescription is not used on iOS8+
P
Programming Learner

To Access User Location in iOS 8 you will have to add,

NSLocationAlwaysUsageDescription in the Info.plist 

This will ask the user for the permission to get their current location.


A
Alok

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

https://i.stack.imgur.com/bXyB3.png

NSLocationWhenInUseUsageDescription

https://i.stack.imgur.com/JIwZ0.png

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

https://i.stack.imgur.com/cHdfe.png

https://i.stack.imgur.com/utuWG.png

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

}

Please make sure NSLocationAlwaysUsageDescription is also added otherwise you will get an error while uploading on the app store.
Your message should also be informative otherwise apple will reject the app while reviwing process.
D
Derreck Dean

For those using Xamarin, I had to add the key NSLocationWhenInUseUsageDescription to the info.plist manually since it was not available in the dropdowns in either Xamarin 5.5.3 Build 6 or XCode 6.1 - only NSLocationUsageDescription was in the list, and that caused the CLLocationManager to continue to fail silently.


P
Prosenjit Goswami
        // ** 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]);

}

P
Peter Mortensen

A little helper for all of you that have more than one Info.plist file...

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Add NSLocationWhenInUseUsageDescription string' {} 

It will add the needed tag to all of the Info.plist files in the current directory (and subfolders).

Another is:

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Set NSLocationWhenInUseUsageDescription $YOURDESCRIPTION' {} 

It will add your description to all files.


M
Marco
J
Jorge Luis Jiménez

I get a similar error in iOS9 (working with Xcode 7 and Swift 2): Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first. I was following a tutorial but the tutor was using iOS8 and Swift 1.2. There are some changes in Xcode 7 and Swift 2, I found this code and it works fine for me (if somebody needs help):

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    // MARK: Properties
    @IBOutlet weak var mapView: MKMapView!

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        self.mapView.showsUserLocation = true

    }

    // MARK: - Location Delegate Methods

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let location = locations.last
        let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
        self.mapView.setRegion(region, animated: true)
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("Errors: " + error.localizedDescription)
    }
}

Finally, I put that in info.plist: Information Property List: NSLocationWhenInUseUsageDescription Value: App needs location servers for staff


V
Vinoth Vino

In order to access the users location in iOS. You need to add two keys

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

into the Info.plist file.

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Because I want to know where you are!</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Want to know where you are!</string>

See this below image.

https://i.stack.imgur.com/LZ1df.png


j
juan Isaza

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.


L
Lorenzo

The problem for me was that the class that was the CLLocationManagerDelegate was private, which prevented all the delegate methods from being called. Guess it's not a very common situation but thought I'd mention it in case t helps anyone.


C
Community

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.