【问题标题】:Location Services not working in iOS 8定位服务在 iOS 8 中不起作用
【发布时间】:2014-10-09 17:02:48
【问题描述】:

我在 iOS 7 上运行良好的应用程序不适用于 iOS 8 SDK。

CLLocationManager 不返回位置,我也没有在 Settings -> Location Services 下看到我的应用。我对这个问题进行了谷歌搜索,但没有任何结果。有什么问题?

【问题讨论】:

  • 您也可以将此作为解决方案的参考应用程序github.com/jbanford/ConstantLocationUpdates
  • 我在这里发布了关于 iOS 8 中位置管理器的一些更改:nevan.net/2014/09/core-location-manager-changes-in-ios-8
  • 你可以尝试使用这个库,它简化了核心位置 API 并公开了一个基于块的漂亮接口,并规范了不同 iOS 版本之间的所有差异(完全披露:我是作者):@987654323 @
  • 我在这里找到了一些参考资料datacalculation.blogspot.in/2014/11/…
  • @nevanking 你先生!需要皇冠!自从更改以来,我一直在与这个问题作斗争,但还没有找到如何解决它的“指南”,这对菜鸟很友好。你的指南像我一样是个白痴,我自己处理这个问题。非常感谢您提供的链接。

标签: objective-c ios8 location cllocationmanager


【解决方案1】:

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

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

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

如需更多详细信息,请查看:Core-Location-Manager-Changes-in-ios-8

【讨论】:

  • 你能分享你在 Info.plist 中更新的确切价值吗?我无法在我的 Info.plist 中看到该键。我添加了它,但它似乎仍然不起作用。我正在使用 Swift、iOS8 和 XCode 6 beta 4
  • @Vjay - 你必须在编辑器中编辑 Info.plist 文件,不能在 Xcode 中设置这些键(从 beta 6 开始)。
  • 提醒一下,如果您不想向用户显示自定义解释,只需将此键设置为空字符串即可。
  • 您需要保留您的 locationManager 才能使其正常工作。所以让你的 CLLocationManager 成为一个强大的属性
  • 我'喜欢'你没有收到任何错误,没有警告,没有日志消息,如果你遗漏了 plist 条目,什么都没有。基本上,如果您没有适当的 plist 条目,Apple 已经创建了一个 API 调用,它什么都不做。感谢@OrtwinGentz 解决这个问题。
【解决方案2】:

Objective-C 过程 请按照以下说明操作:

适用于 iOS-11 对于 iOS 11,请查看此答案:iOS 11 location access

需要在 plist 中添加两个 Key 并提供如下图所示的消息:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

适用于 iOS-10 及以下版本:

NSLocationWhenInUseUsageDescription

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
    [locationManager requestWhenInUseAuthorization];
}else{
    [locationManager startUpdatingLocation];
} 

委托方法

#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];
}

快速程序

按照以下说明进行操作:

适用于 iOS-11 对于 iOS 11,请查看此答案:iOS 11 location access

需要在 plist 中添加两个 Key 并提供如下图所示的消息:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

适用于 iOS-10 及以下版本:

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

委托方法

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

}

【讨论】:

  • 请确保也添加了NSLocationAlwaysUsageDescription,否则在应用商店上传时会出错。
  • 您的信息也应该提供信息,否则苹果将在审查过程时拒绝该应用程序。
【解决方案3】:

具有向后兼容性且不会产生 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];
}

设置NSLocationWhenInUseUsageDescription 键入您的Info.plist

对于 iOS 版本 11.0+: 设置NSLocationAlwaysAndWhenInUseUsageDescription 键入您的Info.plist。连同其他 2 个键。

【讨论】:

  • 这不正确,kCLAuthorizationStatusDenied的情况呢?它跳转到 else 并开始更新不正确的位置!
  • 这很奇怪,这对我来说很好,在允许和不允许的情况下都很好。即使雅各布解决方案看起来很准确,但对我不起作用。奇怪但有效!!!
  • 在 requestWhenInUseAuthorization 之后立即调用 [self.locationManager startUpdatingLocation] 没有意义
【解决方案4】:

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

将此添加到您的代码中

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

【讨论】:

  • 不清楚你的伪代码是预处理器调用还是常规调用
  • 将此添加到您的 constants.h 或 .pch 文件中:#define IS_OS_8_OR_LATER ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)
  • 你为什么要两者都要求,你应该添加一个评论,只根据你的应用需要使用一个或另一个
  • info.plist 部分在 Unity3d 中很容易做到,但是如果使用 unity3d 我将如何添加代码部分?在哪里?
【解决方案5】:

根据 Apple 文档:

从 iOS 8 开始,您的应用的 Info.plist 文件中必须存在 NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription 键值。然后还需要在注册位置更新之前请求用户的许可,根据您的需要调用[self.myLocationManager requestWhenInUseAuthorization][self.myLocationManager requestAlwaysAuthorization]。您在 Info.plist 中输入的字符串随后将显示在随后的对话框中。

如果用户授予权限,一切照旧。如果他们拒绝许可,则不会通知代理人位置更新。

【讨论】:

【解决方案6】:

为了在 iOS 中访问用户的位置。你需要添加两个键

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

进入 Info.plist 文件。

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

见下图。

【讨论】:

    【解决方案7】:

    我也遇到了同样的问题。 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>
    

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

    你可以找到更多关于这两个设置here的信息

    【讨论】:

    • xcode 6 默认不添加这些键,如果你打算实现 CLLocationManager 必须手动添加它们
    • 我也不得不手动添加这些,无法通过 Xcode6 中 info.plist 的 RawValues 视图添加!
    • 我一直在寻找这个。我的 [CLLLocationManager authorizationStatus] 消息仅返回 值。添加上述键后,它开始返回消息输出的相应枚举。根据我的发现,这是一个已知的 iOS 8 错误,但多年来在我的上下文中找不到任何东西。谢谢一百万!
    • 我喜欢你输入的字符串值
    • 该消息将显示为警报中的子消息,询问用户是否愿意分享他们的位置。因此,简单地为空(空白)似乎在我的应用程序中最有意义。解释为什么要使用位置也是有道理的。但是, NSLocationWhenInUseUsageDescription 对我来说并没有像预期的那样运行(即,即使返回值是正确的,也一直被拒绝许可)。 NSLocationAlwaysUsageDescription 工作正常。
    【解决方案8】:

    我在 iOS9 中遇到了类似的错误(使用 Xcode 7 和 Swift 2): 尝试在不提示位置授权的情况下启动 MapKit 位置更新。必须先调用 -[CLLocationManager requestWhenInUseAuthorization] 或 -[CLLocationManager requestAlwaysAuthorization]。 我正在学习教程,但导师使用的是 iOS8 和 Swift 1.2。 Xcode 7 和 Swift 2 有一些变化,我发现这段代码对我来说很好用(如果有人需要帮助):

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

    最后,我把它放在 info.plist 中: 信息属性列表:NSLocationWhenInUseUsageDescription 价值:应用需要为员工提供位置服务器

    【讨论】:

      【解决方案9】:
      - (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
      
      
      }
      

      到你的 info.plist 文件

      【讨论】:

      • datacalculation.blogspot.in/2014/11/…以更具描述性的方式找到了类似的解决方案
      • @Hemang:根据Apple Dev Documentation:在确定您的应用程序的授权状态之前启动位置服务是安全的。虽然您可以启动定位服务,但这些服务在授权状态更改为 kCLAuthorizationStatusAuthorizedAlways 或 kCLAuthorizationStatusAuthorizedWhenInUse 之前不会传递任何数据。
      • 有点晚了,但我建议你隐藏你的 plist 文件中不相关的部分,尤其是 FacebookAppID
      • 谢谢,但这只是一个虚拟样本:)
      • 项目指向 right info.plist(定义密钥的那个)也很重要。这在 Info.plist 文件下的项目构建设置中确定。
      【解决方案10】:

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

      if (IS_OS_8_OR_LATER)
      {
          [locationmanager requestWhenInUseAuthorization];
      
          [locationmanager requestAlwaysAuthorization];
      }
      

      到 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 在 iOS8+ 上不使用
      【解决方案11】:

      Cocoa Keys 信息随时掌握在您的指尖,以获取这些更新,这里是链接:

      https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW26

      享受吧。

      【讨论】:

        【解决方案12】:

        我在 iOS 8.4、iPad mini 2 中将这些密钥添加到 InfoPlist.strings 它也可以。我没有在我的Info.plist 中设置任何键,例如NSLocationWhenInUseUsageDescription


        InfoPlist.strings

        "NSLocationWhenInUseUsageDescription" = "I need GPS information....";
        

        Base on this thread,它说,as in iOS 7,可以在 InfoPlist.strings 中本地化。在我的测试中,这些键可以直接在文件InfoPlist.strings中配置。

        因此,您需要做的第一件事是将以下一个或两个键添加到您的 Info.plist 文件中:

        • NSLocationWhenInUseUsageDescription
        • NSLocationAlwaysUsageDescription

        这两个键都带有一个字符串,该字符串描述了您为什么 需要定位服务。您可以输入一个字符串,例如“Location is 需要找出你在哪里”,就像在 iOS 7 中一样,可以 在 InfoPlist.strings 文件中本地化。


        更新:

        我认为@IOS's method is better. 将键添加到具有空值的Info.plist 并将本地化字符串添加到InfoPlist.strings

        【讨论】:

          【解决方案13】:

          我的问题是 CLLocationManagerDelegate 的类是私有的,这会阻止调用所有委托方法。猜猜这不是一个很常见的情况,但我想我会提到它以防对任何人有帮助。

          【讨论】:

            【解决方案14】:
            - (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];
                    }
                }
            

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

            • NSLocationWhenInUseUsageDescription
            • NSLocationAlwaysUsageDescription

            这两个键都有一个字符串

            这是对您需要定位服务的原因的描述。你可以 输入一个字符串,例如“需要位置才能找出您所在的位置” 与 iOS 7 一样,可以在 InfoPlist.strings 文件中进行本地化。

            【讨论】:

              【解决方案15】:

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

              首先确保为 NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription 添加一个值到 plist。

              如果您仍然没有看到要求授权的弹出窗口,请查看您是否将var locationManager = CLLocationManager() 行放入视图控制器的viewDidLoad 方法中。如果你这样做了,那么即使你打电话给locationManager.requestWhenInUseAuthorization(),也不会显示任何内容。这是因为 viewDidLoad 执行后,locationManager 变量被释放(清除)。

              解决方法是在类方法的顶部找到var locationManager = CLLocationManager()这一行。

              【讨论】:

                【解决方案16】:

                我正在开发一个升级到 iOS 8 的应用,但位置服务停止工作。您可能会在 Debug 区域出现如下错误:

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

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

                - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:  (CLAuthorizationStatus)status
                {
                    [self gotoCurrenLocation];
                }
                

                现在一切正常。与往常一样,请查看documentation

                【讨论】:

                  【解决方案17】:

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

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

                  编辑您应用的Info.plist 并添加键NSLocationAlwaysUsageDescription 以及将向用户显示的字符串值(例如,We do our best to preserve your battery life.

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

                  requestAlwaysAuthorizationrequestWhenInUseAuthorization

                  NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription

                  【讨论】:

                    【解决方案18】:

                    为拥有多个 Info.plist 文件的所有人提供一个小帮手...

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

                    它将所需的标签添加到当前目录(和子文件夹)中的所有 Info.plist 文件中。

                    另一个是:

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

                    它将您的描述添加到所有文件中。

                    【讨论】:

                      【解决方案19】:

                      询问位置的旧代码在 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];
                          }
                      }
                      

                      【讨论】:

                      • UIAlertView 已被弃用。您应该改用 UIAlertController。
                      • 是的,我知道它已被弃用,但这也可以。但是是的,最好将 UIAlertController 用于 IOS8。
                      【解决方案20】:

                      我可以在 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];
                      

                      【讨论】:

                      • 不错的动态解决方案,可用于所有应用程序。我会更改订单,而不是检查 iphone 8.0,我会检查位置管理器是否响应授权,然后运行授权状态以获取代码。这将使其更加通用。
                      • 也曾在 xCode 7.2 上工作过。
                      【解决方案21】:

                      对于使用 Xamarin 的用户,我必须手动将密钥 NSLocationWhenInUseUsageDescription 添加到 info.plist,因为它在任一 Xamarin 5.5 的下拉列表中均不可用。 3 Build 6 或 XCode 6.1 - 只有 NSLocationUsageDescription 在列表中,这导致 CLLocationManager 继续静默失败。

                      【讨论】:

                        【解决方案22】:
                                // ** 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]);
                        
                        }
                        

                        【讨论】:

                          【解决方案23】:

                          要在 iOS 8 中访问用户位置,您必须添加,

                          NSLocationAlwaysUsageDescription in the Info.plist 
                          

                          这将要求用户获得他们当前位置的权限。

                          【讨论】:

                            【解决方案24】:
                            1. 添加键 NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription(后台 GPS 使用),字符串要求在每个目标的每个 info.plist 上使用 GPS。

                            2. 通过运行请求许可:

                              [self initLocationManager:locationManager];

                            initLocationManager 在哪里:

                            // asks for GPS authorization on iOS 8
                            -(void) initLocationManager:(CLLocationManager *) locationManager{
                            
                                locationManager = [[CLLocationManager alloc]init];
                            
                                if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
                                    [locationManager requestAlwaysAuthorization];
                            }
                            

                            请记住,如果每个目标的每个 info.plist 上都没有键,则应用不会询问用户。 if 提供与 iOS 7 的兼容性,respondsToSelector: 方法保证未来的兼容性,而不仅仅是解决 iOS 7 和 8 的问题。

                            【讨论】:

                              【解决方案25】:

                              向后兼容的解决方案:

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

                              在 Info.plist 中设置 NSLocationWhenInUseUsageDescription 键

                              【讨论】:

                              • 这不正确,kCLAuthorizationStatusDenied的情况呢?它跳转到 else 并开始更新不正确的位置!
                              • @BenMarten 我认为这无关紧要。您应该使用locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error 自己处理。但是,他确实忘记将 startUpdatingLocation 添加到 if 语句中,因此在他们接受或拒绝它之后,它实际上并没有调用 startUpdateLocation。
                              【解决方案26】:

                              为确保向后兼容 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];
                              

                              【讨论】:

                              • 比检查版本更好的方法是检查对象是否具有该选择器,例如:if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
                              • 在 Xcode 5 上构建时,我在实现 @progrmr 的解决方案时遇到了麻烦,因为它不知道 requestAlwaysAuthorization 方法是什么。我的另一个解决方案是在if 语句中使用这一行而不是普通的方法调用:[self.locationManager performSelector:@selector(requestAlwaysAuthorization)];。也许这对其他人来说很明显,但我花了一段时间才弄清楚。在最终的 Xcode 6 发布之前,我认为这是正确的解决方案。
                              • 正确的解决方案是使用 Xcode 6 构建。如果您使用 Xcode 5 构建,则无需请求授权,它是自动的。
                              • 你可能有一点。我担心的是,当我的团队转换到 Xcode 6 时,我希望我的代码在 Xcode 5 中编译(即使它不能在 iOS 8 上运行,除非在 Xcode 6 中编译)。但通常编写代码可能是一个更好的工作流程并且在我们迁移到 Xcode 6 之前不要合并它。谢谢。
                              • @VinceFi 或推荐的方法是使用 SDK 定义的宏 __IPHONE_OS_VERSION_MAX_ALLOWED (#if __IPHONE_OS_VERSION_MAX_ALLOWED &gt;= 80000) 有条件地编译
                              猜你喜欢
                              • 2014-11-22
                              • 2017-11-09
                              • 2013-09-27
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多