【问题标题】:CLLocationManager never asks user about location servicesCLLocationManager 从不向用户询问位置服务
【发布时间】:2015-05-31 06:46:11
【问题描述】:

我有一个仅限 IOS 8 的应用程序,我想在其中使用位置服务来获取设备的纬度和经度。我想我已经正确实现了一切,但是应用程序从不询问用户是否可以使用位置服务,CLAuthorizationStatus 永远不会从 kCLAuthorizationStatusNotDetermined 和 CLLocationManager 委托方法更改

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

永远不会被调用。

这是在视图控制器的接口文件中定义的 CLLocationManager:

__strong CLLocationManager *locationManager;

这是视图控制器中的代码:

- (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
}

应用的 Info.plist 文件有一个 NSLocationWhenInUseUsageDescription 条目。

调试跟踪显示该行

[locationManager requestWhenInUseAuthorization];

被执行,但没有出现要求用户确认定位服务的对话框。

此应用程序中的定位服务在 iOS 7 下正常工作 - 我显然做错了什么,或者没有做我需要做的事情以使其在 iOS 8 中工作。但我一直在寻找洞察力,看起来对我来说,好像我做的一切都是正确的。

有什么想法和/或建议吗?提前致谢。

【问题讨论】:

标签: ios objective-c cllocationmanager


【解决方案1】:

我找到了解决方案,但我不知道为什么。我意识到我在应用程序文件夹的不同文件夹中有重复的 info.plists。这两个 info.plist 看起来是相同的,都带有 NSLocationWhenInUseUsageDescription 条目。但是,当我删除应用程序导航窗口中未提及的应用程序时,该应用程序开始像宣传的那样工作:收到请求警报,允许定位服务,并且标题开始更新。不知道为什么不包含在应用程序构建中的相同重复 info.plist 会导致该问题,但似乎确实如此。

【讨论】:

    【解决方案2】:

    首先,检查 CLLocationManagerDelegate 是否定义,然后执行如下操作。

    NSString *systenversion=[[UIDevice currentDevice] systemVersion];
    
        if ([systenversion integerValue]>=8.0) {
    
            if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
                [locationManager requestAlwaysAuthorization];
            }
        }
        [locationManager startUpdatingLocation];
    

    和代表们,

    - (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;
        }
    }
    

    希望这行得通。 :)

    【讨论】:

    • 感谢您的回复,光辉。请参阅上面我对布赖恩的回复。 locationManager:didChangeAuthorizationStatus 确实由 locationManager 调用,但他的状态始终为未确定。询问用户是否允许使用定位服务的对话框永远不会出现。
    • 在 info.plist 中添加一行 NSLocationWhenInUseUsageDescription = YES
    【解决方案3】:

    你已经很接近了。让我看看能不能帮上忙。对于 iOS 8,您需要先调用:

    [self.locationManager requestWhenInUseAuthorization];
    

    我建议将其放在您的代码行之后:locationManager.delegate = self;(然后删除您的 viewDidLoad 方法中的所有其他内容)。由于所有新的隐私内容,这与 iOS 7 不同。在调用此方法的委托回调之前不要调用startUpdatingLocation。如果您阅读文档,您会看到方法requestWhenInUseAuthorization 在完成后会调用其回调方法:

    locationManager:didChangeAuthorizationStatus:
    

    在回调方法中,检查状态并根据该值是什么采取措施。这是我的方法的样子:

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

    请注意,您不会每次都看到询问应用是否可以使用您的位置的提醒。看过一次之后,就不会再出现了。然后,用户可以控制该应用是否可以在设备上的设置应用中访问他/她的位置。

    【讨论】:

    • 最后一条评论遇到了问题...这是我想补充的内容:谢谢您的回复,Brian。我确实调用了“locationManager:requestWhenInUseAuthorization”方法,而 CLLocationManager 确实调用了locationManager:didChangeAuthorizationStatus 委托方法,但状态始终为 kCLAuthorizationStatusNotDetermined。将 locationManager: startUpdatingLocation 方法移至 didChangeAuthorizationStatus 似乎没有任何改变:询问用户是否允许使用位置服务的警报从未出现。
    • 好吧,这很有趣。您是否在设备上启用了定位服务?您可以通过进入设备上的设置应用程序或查看此方法返回的内容进行检查:[CLLocationManager locationServicesEnabled]
    • 定位服务已启用,同时显示在设置和CLLocationManager locationServicesEnabled. 的返回我毫不怀疑这将是其中之一“拍打额头并大喊‘为什么我没有想到这一点很久以前?'”的回答,但就目前而言,这真的让我着迷。谢谢你的帮助,布赖恩。
    • 是的,这是一个棘手的问题。我唯一能想到的另一件事是将 requestWhenInUseAuthorization 的调用移至 viewWillAppear 或 viewDidAppear。有时在 viewDidLoad 中操作视图层次结构会搞砸。
    • 不幸的是,移动代码不走运。一个可能不相关的事实是位置管理器确实提供了正确的航向信息。我假设用户所需的权限仅适用于位置,而不适用于标题。虽然我似乎总是在 Stack Overflow 上得到更好的答案,但我会在开发者论坛上发布此内容,并希望了解 CLLocationManager 的 Apple 人能同情我……再次感谢 Brian。
    猜你喜欢
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-12
    • 2012-03-30
    相关资源
    最近更新 更多