位置服务在iOS 8中不起作用

özg*_*özg 606 location objective-c cllocationmanager ios8

我在iOS 7上运行良好的应用程序无法与iOS 8 SDK一起使用.

CLLocationManager没有返回位置,我也没有在设置 - > 位置服务下看到我的应用程序.我在这个问题上进行了谷歌搜索,但没有出现任何问题.可能有什么不对?

özg*_*özg 1086

我最终解决了自己的问题.

显然,在开始位置更新之前,需要在iOS 8 SDK中requestAlwaysAuthorization(对于后台位置)或requestWhenInUseAuthorization(仅在前景时的位置)调用CLLocationManager.

还需要输入NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription键入Info.plist要在提示中显示的消息.添加这些解决了我的问题.

在此输入图像描述

希望它可以帮助别人.

编辑:有关更多信息,请查看:Core-Location-Manager-Changes-in-ios-8

  • 我'爱'你没有错误,没有警告,没有日志消息,如果你遗漏了plist条目,那就没有了.基本上Apple已经创建了一个API调用,如果你没有相应的plist条目,那么它就没有了.感谢@OrtwinGentz解决这个问题. (272认同)
  • 只是提醒一下,如果您不想向用户显示自定义说明,只需将此键设置为空字符串即可. (11认同)
  • 您需要保留locationManager才能使其正常工作.所以将您的CLLocationManager作为一个强大的属性 (7认同)
  • 你可以分享Info.plist中更新的确切值吗?我无法在Info.plist中看到该密钥.我添加了它,但它似乎无法正常工作.我使用的是Swift,iOS8和XCode 6 beta 4 (6认同)
  • @Vjay - 你必须在编辑器中编辑Info.plist文件,不能在Xcode中设置这些键(从beta 6开始). (4认同)
  • 以下是WWDC 2014的相关PDF,描述了开发人员需要实施的变更(第108和116页):http://devstreaming.apple.com/videos/wwdc/2014/706xxjytntg51wd/706/706_whats_new_in_core_location.pdf?dl = 1 (2认同)
  • 我做了这两件事但仍然没有骰子......用户永远不会得到提示,即使是全新安装.我甚至进入设置并为我的应用程序手动启用了位置服务,并且STILL没有获得任何位置更新,并且auth状态始终是"未确定".我很沮丧苹果因为搞砸了这个并打破了很多非常好的代码.但是,这就是生活. (2认同)

Hen*_*nry 313

我也在用同样的问题拔出头发.Xcode为您提供错误:

尝试在MapKit不提示位置授权的情况下启动位置更新.必须打电话-[CLLocationManager requestWhenInUseAuthorization]-[CLLocationManager requestAlwaysAuthorization]先打电话

但即使你实现了上述方法之一,它也不会提示用户,除非info.plist中有一个条目NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription.

将以下行添加到info.plist,其中字符串值表示您需要访问用户位置的原因

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

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
Run Code Online (Sandbox Code Playgroud)

我认为自从我在Xcode 5中启动这个项目后,这些条目可能已经丢失.我猜Xcode 6可能会为这些键添加默认条目但尚未确认.

您可以在此处找到有关这两个设置的更多信息

  • 默认情况下,xcode 6不会添加这些键,如果您打算实现CLLocationManager,则必须手动添加它们 (13认同)
  • 我喜欢你输入的字符串值 (4认同)

JKo*_*oko 104

为了确保这与iOS 7向后兼容,您应该检查用户是运行iOS 8还是iOS 7.例如:

#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];
Run Code Online (Sandbox Code Playgroud)

  • 比检查版本更好的方法是检查对象是否具有该选择器,例如:`if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){...` (164认同)
  • 正确的解决方案是使用Xcode 6构建.如果您使用Xcode 5构建,则无需请求授权,它是自动的. (2认同)

neo*_* D1 50

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


}
Run Code Online (Sandbox Code Playgroud)

并到您的info.plist文件 在此输入图像描述

  • @Hemang:根据Apple Dev Documentation:在确定应用程序的授权状态之前启动位置服务是安全的.虽然您可以启动位置服务,但在授权状态更改为kCLAuthorizationStatusAuthorizedAlways或kCLAuthorizationStatusAuthorizedWhenInUse之前,这些服务不会传递任何数据. (2认同)

met*_*tic 30

根据Apple文档:

从iOS 8开始,您需要在应用的Info.plist文件中显示一个NSLocationWhenInUseUsageDescription或一个NSLocationAlwaysUsageDescription键值.然后,在注册位置更新之前,还需要通过呼叫[self.myLocationManager requestWhenInUseAuthorization][self.myLocationManager requestAlwaysAuthorization]根据您的需要请求用户的许可.然后,您在Info.plist中输入的字符串将显示在随后的对话框中.

如果用户授予权限,则照常营业.如果他们拒绝许可,则不会通知代表位置更新.


Ada*_*G J 28

- (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];
        }
    }
Run Code Online (Sandbox Code Playgroud)

在iOS 8中,您需要做两件额外的事情才能使位置正常工作:在Info.plist中添加一个密钥,并向位置管理员请求授权以启动它.新位置授权有两个Info.plist键.需要这些键中的一个或两个.如果两个键都不存在,则可以调用startUpdatingLocation,但位置管理器实际上不会启动.它也不会向委托发送失败消息(因为它从未启动过,它不会失败).如果您添加一个或两个密钥但忘记明确请求授权,它也将失败.因此,您需要做的第一件事是将以下一个或两个密钥添加到Info.plist文件中:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

这两个键都带有一个字符串

这是对您需要位置服务的原因的描述.您可以输入一个字符串,如"需要位置以查找您所在的位置",如iOS 7中所示,可以在InfoPlist.strings文件中进行本地化.

在此输入图像描述


Yin*_*eng 19

我的解决方案可以在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];
Run Code Online (Sandbox Code Playgroud)

  • 漂亮的动态解决方案,可在所有应用中使用.我会更改顺序,而不是检查iphone 8.0,我会检查位置管理器是否响应授权,然后运行authorizationstatus来获取代码.这将使其更具普遍性. (2认同)

Nit*_*7ak 17

询问位置的旧代码在iOS 8中不起作用.您可以尝试使用此方法进行位置授权:

- (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];
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 12

在iOS 8中,您需要做两件额外的事情才能使位置正常工作:在Info.plist中添加一个密钥,并向位置管理员请求授权,要求它启动

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>
Run Code Online (Sandbox Code Playgroud)

将其添加到您的代码中

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}
Run Code Online (Sandbox Code Playgroud)


st.*_*ick 11

Swift开发人员的一个常见错误:

首先确保为plist中的一个NSLocationWhenInUseUsageDescription或者添加一个值NSLocationAlwaysUsageDescription.

如果您仍然没有看到弹出窗口要求授权,请查看您是否将该行var locationManager = CLLocationManager()放入View Controller的viewDidLoad方法中.如果你这样做,那么即使你打电话locationManager.requestWhenInUseAuthorization(),也不会出现任何信息.这是因为在viewDidLoad执行之后,将取消分配(清除)locationManager变量.

解决方案是将行定位var locationManager = CLLocationManager()在类方法的顶部.


bud*_*ino 9

之前[locationManager startUpdatingLocation];,添加iOS8位置服务请求:

if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    [locationManager requestAlwaysAuthorization];
Run Code Online (Sandbox Code Playgroud)

编辑应用程序Info.plistNSLocationAlwaysUsageDescription使用将显示给用户的字符串值添加键(例如We do our best to preserve your battery life.)

如果您的应用仅在应用开放时需要位置服务,请替换:

requestAlwaysAuthorizationrequestWhenInUseAuthorization

NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription.


小智 9

我正在开发一个升级到iOS 8且位置服务停止运行的应用程序.您可能会在调试区域中得到错误,如下所示:

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

我做了最少侵入性的程序.首先NSLocationAlwaysUsageDescription在info.plist中添加条目:

在此输入图像描述

注意我没有填写此密钥的值.这仍然有效,我并不担心,因为这是一个内部应用程序.此外,已经有一个标题要求使用位置服务,所以我不想做任何多余的事情.

接下来我为iOS 8创建了一个条件:

if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
    [_locationManager requestAlwaysAuthorization];
}
Run Code Online (Sandbox Code Playgroud)

在此之后,该locationManager:didChangeAuthorizationStatus:方法被调用:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:  (CLAuthorizationStatus)status
{
    [self gotoCurrenLocation];
}
Run Code Online (Sandbox Code Playgroud)

现在一切正常.与往常一样,查看文档.


hrc*_*hen 7

向后兼容的解决方案:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}
Run Code Online (Sandbox Code Playgroud)

在Info.plist中设置NSLocationWhenInUseUsageDescription键

  • 这不正确,kCLAuthorizationStatusDenied案件怎么样?它跳转到else并开始更新不正确的位置! (2认同)

Ale*_*kiy 6

具有向后兼容性的解决方案,不会产生Xcode警告:

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];
}
Run Code Online (Sandbox Code Playgroud)

NSLocationWhenInUseUsageDescription你的设置键Info.plist.

对于iOS版本11.0+:NSLocationAlwaysAndWhenInUseUsageDescription您的安装密钥Info.plist.以及其他2个键.


小智 5

这是ios 8的问题将此添加到您的代码中

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}
Run Code Online (Sandbox Code Playgroud)

和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>
Run Code Online (Sandbox Code Playgroud)