首页 文章

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

提问于
浏览
603

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

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

26 回答

  • 2

    对于那些使用 Xamarin 的人,我必须手动将密钥 NSLocationWhenInUseUsageDescription 添加到info.plist,因为它在Xamarin 5.5.3 Build 6或XCode 6.1的下拉列表中不可用 - 只有 NSLocationUsageDescription 在列表中,这导致 CLLocationManager 继续默默地失败 .

  • 0

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

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

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

    enter image description here

    希望它可以帮助别人 .

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

  • 30

    我也在用同样的问题拔出头发 . 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

  • 50

    为了确保这与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];
    
  • 28
    - (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文件
    enter image description here

  • 2

    根据Apple文档:

    从iOS 8开始,在注册位置更新之前,还需要在您的app 's Info.plist file is required. It'中存在 NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription 键值,以便根据需要调用 [self.myLocationManager requestWhenInUseAuthorization][self.myLocationManager requestAlwaysAuthorization] 来请求用户的许可 . 然后,您在Info.plist中输入的字符串将显示在随后的对话框中 .

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

  • 11
    - (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文件中进行本地化 .

    enter image description here

  • 1

    我的解决方案可以在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];
    
  • 6

    这是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>
    
  • 2

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

    NSLocationAlwaysUsageDescription in the Info.plist
    

    这将要求用户获得获取其当前位置的许可 .

  • 4

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

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

    Add this to your code

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

    One common error for Swift developers:

    首先确保为 NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription 的plist添加值 .

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

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

  • 312

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

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

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

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

    requestAlwaysAuthorizationrequestWhenInUseAuthorization

    NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription .

  • 3

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

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

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

    Enter image description here

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

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

    if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [_locationManager requestAlwaysAuthorization];
    }
    

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

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

    现在一切正常 . 一如既往,请查看documentation .

  • 0

    向后兼容的解决方案:

    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键

  • 12

    具有向后兼容性的解决方案,不会产生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];
    }
    

    Info.plist 中设置 NSLocationWhenInUseUsageDescription 键 .

    For iOS version 11.0+ :在 Info.plist 中设置 NSLocationAlwaysAndWhenInUseUsageDescription 键 . 以及其他2个键 .

  • 1084

    Objective-C Procedure 按照以下说明操作:

    For iOS-11 对于iOS 11看看这个答案:iOS 11 location access

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

    1. NSLocationAlwaysAndWhenInUseUsageDescription 
     2. NSLocationWhenInUseUsageDescription
     3. NSLocationAlwaysUsageDescription
    

    enter image description here
    For iOS-10 and below:

    NSLocationWhenInUseUsageDescription
    

    enter image description here

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

    Swift Procedure

    请按照以下说明操作:

    For iOS-11 对于iOS 11看看这个答案:iOS 11 location access

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

    1. NSLocationAlwaysAndWhenInUseUsageDescription 
     2. NSLocationWhenInUseUsageDescription
     3. NSLocationAlwaysUsageDescription
    

    enter image description here
    For iOS-10 and below:

    enter image description here

    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
    
    }
    
  • 5
    // ** 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]);
    
    }
    
  • 3

    对于拥有多个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

    保持 Cocoa Keys 信息总是触手可及,以获取这些更新,以下是链接:

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

    请享用 .

  • 17

    我在iOS9中遇到了类似的错误(使用Xcode 7和Swift 2): Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first. 我正在关注一个教程,但导师使用的是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 值: App needs location servers for staff

  • 9

    为了访问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>
    

    见下图 .

    Info.plist image

  • 9
    • 添加键 NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription (背景GPS使用),字符串要求在每个目标的每个 info.plist 上使用GPS .

    • 通过运行请求权限:

    [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的问题 .

  • 2

    对我来说问题是 CLLocationManagerDelegate 的类是私有的,它阻止了所有委托方法的调用 . 猜猜's not a very common situation but thought I' d提到它,以防t帮助任何人 .

  • 7

    我在 iOS 8.4, iPad mini 2. 中添加了这些键 iOS 8.4, iPad mini 2. 它也有效 . 我没有在 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这两个键都带有一个字符串,该字符串描述了您需要位置服务的原因 . 您可以输入一个字符串,如“需要位置以查找您所在的位置”,如iOS 7中所示,可以在InfoPlist.strings文件中进行本地化 .


    UPDATE:

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

相关问题