iOS 8不支持位置服务

我的应用在ios7上运行良好,但在ios8 SDK上却无法运行。

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

281661 次浏览

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

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

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

enter image description here

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

我也因为同样的问题而抓狂。Xcode给出错误:

尝试启动MapKit位置更新而没有提示 位置授权。-[CLLocationManager ? requestWhenInUseAuthorization]-[CLLocationManager . CLLocationManager . requestAlwaysAuthorization] < /代码>。< / p >

但即使实现了上述方法之一,它也不会提示用户,除非信息中有条目。plist为NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription

添加以下行到您的信息。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可能会为这些键添加默认条目,但还没有确认。

您可以找到关于这两个设置在这里的更多信息

苹果的文件显示:

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

如果用户授予了权限,则业务照常进行。如果他们拒绝权限,则委托不会被告知位置更新。

为了确保这与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];

向后兼容解决方案:

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键

解决方案与向后兼容,不产生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键。

< p > # EYZ0: 在Info.plist中设置NSLocationAlwaysAndWhenInUseUsageDescription键。还有另外2把钥匙。< / p >

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

用于询问位置的旧代码将无法在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];
}
}
- (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




}

和你的信息。plist文件 enter image description here

在iOS 8中,你需要做两件额外的事情来让定位工作:给你的信息添加一个键。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];
}

一个小帮手,为所有你有一个以上的信息。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' {}

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

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

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

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

如果你的应用程序只在应用程序打开时需要位置服务,请替换:

requestAlwaysAuthorizationrequestWhenInUseAuthorization

NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription

  1. 添加键NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription(背景GPS使用)与字符串要求使用GPS在每个info.plist从每个目标。

  2. 通过run请求允许:

    (自我initLocationManager: locationManager); < / p >

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

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

NSLocationAlwaysUsageDescription in the Info.plist

这将询问用户获取其当前位置的权限。

        // ** 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]);


}

对于那些使用Xamarin的的人,我必须在信息中添加NSLocationWhenInUseUsageDescription键。因为在Xamarin 5.5.3 Build 6或XCode 6.1的下拉列表中都无法使用plist,所以只能手动执行,只有NSLocationUsageDescription在列表中,这导致CLLocationManager继续默默失败。

我当时在开发一款升级到ios 8的应用程序,位置服务停止了。你可能会在Debug区域得到一个错误,如下所示:

# EYZ0

我做了侵入性最小的手术。首先添加NSLocationAlwaysUsageDescription条目到你的info.plist:

Enter image description here

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

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

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

然后调用locationManager:didChangeAuthorizationStatus:方法:

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

现在一切正常。像往常一样,看看文档

- (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中,你需要做两件额外的事情来让位置工作:添加 你的信息的钥匙。Plist并从该位置请求授权 经理要求启动。有两个信息。Plist键的新 位置授权。需要其中一个或两个密钥。如果 两个键都不存在,你可以调用startUpdatingLocation但是 位置管理器实际上不会启动。它不会发送失败 消息也发送给委托(因为它从未启动,所以它不能 失败)。如果您添加了一个或两个键,但忘记了,也会失败 显式地请求授权。所以你要做的第一件事 将下列一个或两个键添加到您的信息中。plist文件:< / p >
  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

这两个键都有一个字符串

这是你为什么需要位置服务的描述。你可以 输入一个字符串,如“位置是必须找到你在哪里” 和iOS 7一样,可以在InfoPlist中进行本地化。字符串文件。< / p >

enter image description here

Swift开发者常犯的一个错误:

首先,确保在plist中添加了NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription的值。

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

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

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

我在InfoPlist.strings中添加了这些键,在iOS 8.4, iPad mini 2。中也可以。我没有在Info.plist中设置任何键,比如NSLocationWhenInUseUsageDescription


# EYZ0:

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

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

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

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

这两个键都接受一个字符串,这是一个描述为什么你 需要位置服务。您可以输入一个字符串,例如“Location is” 需要找出你在哪里”,就像在iOS 7中一样,可以是 在InfoPlist中本地化。字符串文件。< / p >


更新:

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

这是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>
我在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 值:# EYZ0 < / p >

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

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

进入信息。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. Info. < / >

< >强objective - c程序

.

.

< >强iOS-11 对于iOS 11,看看这个答案:iOS 11位置访问

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

 1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
3. NSLocationAlwaysUsageDescription

enter image description here 对于iOS-10及以下:

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

迅速的过程

遵循以下指示:

< >强iOS-11 对于iOS 11,看看这个答案:iOS 11位置访问

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

 1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
3. NSLocationAlwaysUsageDescription

enter image description here 对于iOS-10及以下:

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


}