618

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

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

4

26 回答 26

1095

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

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

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

在此处输入图像描述

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

于 2014-06-05T14:58:19.103 回答
318

我正在用同样的问题拔头发。Xcode 给你错误:

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

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

将以下行添加到您的 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 可能会为这些键添加默认条目,但尚未确认。

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

于 2014-06-05T15:58:17.173 回答
105

为确保向后兼容 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];
于 2014-06-27T01:14:05.790 回答
51
- (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 文件 在此处输入图像描述

于 2014-09-30T10:24:14.377 回答
30

根据苹果文档:

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

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

于 2014-06-08T22:16:08.220 回答
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];
        }
    }

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

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

这两个键都有一个字符串

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

在此处输入图像描述

于 2014-12-17T03:26:32.483 回答
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];
于 2014-09-24T12:13:05.330 回答
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];
    }
}
于 2014-09-27T09:54:54.937 回答
13

在 iOS 8 中,你需要做两件额外的事情来让位置工作:向你的 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];
}
于 2014-10-02T06:40:00.460 回答
11

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

首先确保为NSLocationWhenInUseUsageDescription或向 plist 添加一个值NSLocationAlwaysUsageDescription

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

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

于 2015-02-17T22:40:17.870 回答
9

我正在开发一个升级到 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];
}

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

于 2014-11-24T16:14:05.550 回答
9

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

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

编辑您的应用程序并使用将向用户显示的字符串值Info.plist添加键(例如, )NSLocationAlwaysUsageDescriptionWe do our best to preserve your battery life.

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

requestAlwaysAuthorizationrequestWhenInUseAuthorization和_

NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription.

于 2014-11-11T14:20:27.390 回答
7

向后兼容的解决方案:

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 键

于 2014-09-11T05:22:19.730 回答
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];
}

NSLocationWhenInUseUsageDescriptionInfo.plist.

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

于 2014-09-11T09:30:59.890 回答
5

这是 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>
于 2015-09-02T07:20:20.837 回答
4

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

NSLocationAlwaysUsageDescription in the Info.plist 

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

于 2014-11-17T04:49:38.010 回答
4

Objective-C 过程 遵循以下说明:

对于 iOS-11 对于 iOS 11 看看这个答案:iOS 11 位置访问

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

 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 位置访问

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

 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

}
于 2017-10-24T04:57:40.570 回答
3

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

于 2014-11-21T16:51:19.653 回答
2
        // ** 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]);

}
于 2014-11-18T13:50:09.900 回答
2

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

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

于 2014-10-07T08:18:12.890 回答
2

Cocoa Keys信息始终触手可及,以获取这些更新,这里是链接:

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

享受。

于 2015-07-30T23:51:02.777 回答
2

我在 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 值:应用程序需要员工的位置服务器

于 2015-12-29T17:19:13.667 回答
2

为了访问用户在 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 图像

于 2017-06-17T03:35:03.630 回答
1
  1. 添加键NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription(背景 GPS 使用)和字符串,要求在info.plist每个目标上使用 GPS。

  2. 通过运行请求许可:

    [自我 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 的问题。

于 2014-11-16T22:04:17.700 回答
0

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

于 2015-07-07T05:34:57.777 回答
0

InfoPlist.strings我在iOS 8.4、iPad mini 2中添加了这些键。它也可以。我没有NSLocationWhenInUseUsageDescription在我的Info.plist.


InfoPlist.strings

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

它说,基于这个线程as in iOS 7,可以在 InfoPlist.strings 中进行本地化。在我的测试中,这些键可以直接在文件中配置InfoPlist.strings

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

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

这两个键都带有一个字符串,该字符串描述了您需要位置服务的原因。您可以输入一个字符串,如“Location is required to find out you are”,就像在iOS 7中一样,可以在 InfoPlist.strings 文件中进行本地化。


更新:

我认为@IOS's 的方法更好。添加Info.plist具有空值的键并将本地化字符串添加到InfoPlist.strings.

于 2015-07-30T09:58:01.870 回答