简体   繁体   中英

CLLocationManager never asks user about location services

I have an IOS 8-only app in which I want to use location services to obtain the device's latitude and longitude. I think I have everything implemented correctly, but the app never asks the user if it's okay to use location services, the CLAuthorizationStatus never changes from kCLAuthorizationStatusNotDetermined and the CLLocationManager delegate method

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading 

never gets called.

Here's the CLLocationManager defined in the interface file for the viewcontroller:

__strong CLLocationManager *locationManager;

Here's the code in the viewcontroller:

- (void)viewDidLoad{
    [super viewDidLoad];

    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
    if (status == kCLAuthorizationStatusNotDetermined) {
        [locationManager requestWhenInUseAuthorization];
    }
    [locationManager startUpdatingLocation];
    //... other viewDidLoad code
}

The Info.plist file for the app has an entry for NSLocationWhenInUseUsageDescription.

Debug tracing shows that the line

[locationManager requestWhenInUseAuthorization];

gets executed, but the dialog requesting the user to okay location services does not appear.

Location services in this app worked correctly under iOS 7 - I'm clearly doing something wrong, or not doing something I need to do to make it work in iOS 8. But I have dug around looking for insights, and it looks to me as if I'm doing everything correctly.

Any ideas and/or suggestions? Thanks in advance.

You're pretty close. Let me see if I can help. For iOS 8, you need to first call:

[self.locationManager requestWhenInUseAuthorization];

I recommend putting this right after your line of code that says: locationManager.delegate = self; (and then delete everything else in your viewDidLoad method). This is different from iOS 7 due to all the new privacy stuff. Don't call startUpdatingLocation until after this method's delegate callback is called. If you read the docs, you'll see that the method requestWhenInUseAuthorization , after finishing, calls its callback method:

locationManager:didChangeAuthorizationStatus:

Within the callback method, check the status and take action depending on what that value is. This is what my method looks like:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    if(status == kCLAuthorizationStatusAuthorized || status == kCLAuthorizationStatusAuthorizedWhenInUse)
    {
        [self.locationManager startUpdatingLocation];
    }
}

Keep in mind that you won't see the alert asking if the app can use your location every time. After you've seen it once, it won't show again. The user can then control whether or not the app can access his / her location in the settings app on the device.

first thing first, check for CLLocationManagerDelegate define or not then, do something like below.

NSString *systenversion=[[UIDevice currentDevice] systemVersion];

    if ([systenversion integerValue]>=8.0) {

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

and the delegates,

- (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: {
            NSLog(@"User still thinking..");
        } break;
        case kCLAuthorizationStatusDenied: {
            NSLog(@"User hates you");
        } break;
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        case kCLAuthorizationStatusAuthorizedAlways: {
            [locationManager startUpdatingLocation];//Will update location immediately

            [self showAlertWithTitle:@"Success" andMessge:@"Success to get current location"];
        } break;
        default:
            break;
    }
}

hope this works. :)

I found the solution, though I don't know why. I realized I had duplicate info.plists in different folders of the app's folder. The two info.plists look to be identical, both with the NSLocationWhenInUseUsageDescription entry. But when I removed the one not referred to in the app's navigation window, the app started to work as advertised: got the request alert, allowed location services and the heading started to update. No idea why an identical duplicate info.plist, not included in the app's build, would cause that problem, but it seems to be the case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM