简体   繁体   English

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

[英]Location Services not working in iOS 8

My app that worked fine on iOS 7 doesn't work with the iOS 8 SDK.我在 iOS 7 上运行良好的应用程序不适用于 iOS 8 SDK。

CLLocationManager doesn't return a location, and I don't see my app under Settings -> Location Services either. CLLocationManager不返回位置,我也没有在“设置” ->“位置服务”下看到我的应用程序。 I did a Google search on the issue, but nothing came up.我对这个问题进行了谷歌搜索,但没有任何结果。 What could be wrong?可能有什么问题?

I ended up solving my own problem.我最终解决了我自己的问题。

Apparently in iOS 8 SDK, requestAlwaysAuthorization (for background location) or requestWhenInUseAuthorization (location only when foreground) call on CLLocationManager is needed before starting location updates.显然在 iOS 8 SDK 中,在开始位置更新之前,需要在CLLocationManager上调用requestAlwaysAuthorization (用于后台位置)或requestWhenInUseAuthorization (仅在前台时定位)。

There also needs to be NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in Info.plist with a message to be displayed in the prompt. Info.plist还需要有NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription键,并在提示中显示一条消息。 Adding these solved my problem.添加这些解决了我的问题。

在此处输入图片说明

For more extensive information, have a look at: Core-Location-Manager-Changes-in-ios-8有关更多信息,请查看: Core-Location-Manager-Changes-in-ios-8

I was pulling my hair out with the same problem.我正在用同样的问题拉我的头发。 Xcode gives you the error: Xcode 给你错误:

Trying to start MapKit location updates without prompting for location authorization.尝试在不提示位置授权的情况下启动MapKit位置更新。 Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.必须先调用-[CLLocationManager requestWhenInUseAuthorization]-[CLLocationManager requestAlwaysAuthorization]

But even if you implement one of the above methods, it won't prompt the user unless there is an entry in the info.plist for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription .但即使您实现了上述方法之一,它也不会提示用户,除非 info.plist 中有NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription

Add the following lines to your info.plist where the string values represent the reason you you need to access the users location将以下行添加到您的 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>

I think these entries may have been missing since I started this project in Xcode 5. I'm guessing Xcode 6 might add default entries for these keys but have not confirmed.我认为自从我在 Xcode 5 中开始这个项目以来,这些条目可能已经丢失了。我猜 Xcode 6 可能会为这些键添加默认条目,但尚未确认。

You can find more information on these two Settings here您可以在此处找到有关这两个设置的更多信息

To ensure that this is backwards compatible with iOS 7, you should check whether the user is running iOS 8 or iOS 7. For example:为确保这与 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];
- (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


}

And to your info.plist File和你的 info.plist 文件在此处输入图片说明

According to the Apple docs:根据苹果文档:

As of iOS 8, the presence of a NSLocationWhenInUseUsageDescription or a NSLocationAlwaysUsageDescription key value in your app's Info.plist file is required.从 iOS 8 开始,应用程序的 Info.plist 文件中需要存在NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription键值。 It's then also necessary to request permission from the user prior to registering for location updates, either by calling [self.myLocationManager requestWhenInUseAuthorization] or [self.myLocationManager requestAlwaysAuthorization] depending on your need.然后还需要在注册位置更新之前请求用户的许可,根据您的需要调用[self.myLocationManager requestWhenInUseAuthorization][self.myLocationManager requestAlwaysAuthorization] The string you entered into the Info.plist will then be displayed in the ensuing dialog.您在 Info.plist 中输入的字符串将显示在随后的对话框中。

If the user grants permission, it's business as usual.如果用户授予权限,则一切照旧。 If they deny permission, then the delegate is not informed of location updates.如果他们拒绝许可,则不会通知代表位置更新。

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

In iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start.在 iOS 8 中,你需要做两件额外的事情来让定位工作:在你的 Info.plist 中添加一个密钥,并从位置管理器请求授权,要求它启动。 There are two Info.plist keys for the new location authorization.新位置授权有两个 Info.plist 密钥。 One or both of these keys is required.需要这些密钥中的一个或两个。 If neither of the keys are there, you can call startUpdatingLocation but the location manager won't actually start.如果两个键都不存在,您可以调用 startUpdatingLocation 但位置管理器实际上不会启动。 It won't send a failure message to the delegate either (since it never started, it can't fail).它也不会向委托发送失败消息(因为它从未启动,所以不会失败)。 It will also fail if you add one or both of the keys but forget to explicitly request authorization.如果您添加一个或两个密钥但忘记明确请求授权,它也会失败。 So the first thing you need to do is to add one or both of the following keys to your Info.plist file:因此,您需要做的第一件事是将以下一个或两个键添加到您的 Info.plist 文件中:

  • NSLocationWhenInUseUsageDescription NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription NSLocationAlwaysUsageDescription

Both of these keys take a string这两个键都需要一个字符串

which is a description of why you need location services.这是您需要定位服务的原因的描述。 You can enter a string like “Location is required to find out where you are” which, as in iOS 7, can be localized in the InfoPlist.strings file.您可以输入类似“Location is required to find your where you are”这样的字符串,就像在 iOS 7 中一样,可以在 InfoPlist.strings 文件中进行本地化。

在此处输入图片说明

My solution which can be compiled in Xcode 5:我的解决方案可以在 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];

The old code for asking location won't work in iOS 8. You can try this method for location authorization:旧的询问位置的代码在 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];
    }
}

In iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start在 iOS 8 中,你需要做两件额外的事情来让定位工作:向你的 Info.plist 添加一个密钥并请求定位管理器的授权,要求它启动

info.plist:信息.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];
}

One common error for Swift developers: Swift 开发人员的一个常见错误:

First make sure you add a value to the plist for either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription .首先确保为NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription添加一个值到 plist。

If you are still not seeing a window pop up asking for authorization, look to see if you are putting the line var locationManager = CLLocationManager() in your View Controller's viewDidLoad method.如果您仍然没有看到请求授权的弹出窗口,请查看您是否将var locationManager = CLLocationManager()放在视图控制器的viewDidLoad方法中。 If you do, then even if you call locationManager.requestWhenInUseAuthorization() , nothing will show up.如果这样做,那么即使您调用locationManager.requestWhenInUseAuthorization() ,也不会显示任何内容。 This is because after viewDidLoad executes, the locationManager variable is deallocated (cleared out).这是因为在 viewDidLoad 执行后,locationManager 变量被释放(清除)。

The solution is to locate the line var locationManager = CLLocationManager() at the top of the class method.解决方案是在类方法的顶部找到行var locationManager = CLLocationManager()

Before [locationManager startUpdatingLocation]; [locationManager startUpdatingLocation];之前[locationManager startUpdatingLocation]; , add an iOS8 location services request: ,添加一个 iOS8 位置服务请求:

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

Edit your app's Info.plist and add key NSLocationAlwaysUsageDescription with the string value that will be displayed to the user (for example, We do our best to preserve your battery life. )编辑您的应用程序的Info.plist并添加键NSLocationAlwaysUsageDescription和将显示给用户的字符串值(例如, We do our best to preserve your battery life.

If your app needs location services only while the app is open, replace:如果您的应用仅在应用打开时才需要定位服务,请替换:

requestAlwaysAuthorization with requestWhenInUseAuthorization and requestAlwaysAuthorizationrequestWhenInUseAuthorization

NSLocationAlwaysUsageDescription with NSLocationWhenInUseUsageDescription . NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription

I was working on an app that was upgraded to iOS 8 and location services stopped working.我正在开发一个升级到 iOS 8 的应用程序,但位置服务停止工作。 You'll probably get and error in the Debug area like so:您可能会在 Debug 区域中得到和错误,如下所示:

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

I did the least intrusive procedure.我做了最少侵入性的程序。 First add NSLocationAlwaysUsageDescription entry to your info.plist:首先将NSLocationAlwaysUsageDescription条目添加到您的 info.plist 中:

在此处输入图片说明

Notice I didn't fill out the value for this key.注意我没有填写这个键的值。 This still works, and I'm not concerned because this is a in house app.这仍然有效,我并不担心,因为这是一个内部应用程序。 Also, there is already a title asking to use location services, so I didn't want to do anything redundant.另外,已经有一个标题要求使用位置服务,所以我不想做任何多余的事情。

Next I created a conditional for iOS 8:接下来我为 iOS 8 创建了一个条件:

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

After this the locationManager:didChangeAuthorizationStatus: method is call:在此之后locationManager:didChangeAuthorizationStatus:方法被调用:

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

And now everything works fine.现在一切正常。 As always, check out the documentation .与往常一样,请查看文档

Solution with backward compatibility:具有向后兼容性的解决方案:

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

Setup NSLocationWhenInUseUsageDescription key in your Info.plist在 Info.plist 中设置 NSLocationWhenInUseUsageDescription 键

Solution with backward compatibility which doesn't produce Xcode warnings:具有向后兼容性且不会产生 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];
}

Setup NSLocationWhenInUseUsageDescription key in your Info.plist .Info.plist设置NSLocationWhenInUseUsageDescription键。

For iOS version 11.0+ : Setup NSLocationAlwaysAndWhenInUseUsageDescription key in your Info.plist .对于 iOS 11.0+ 版本:在Info.plist设置NSLocationAlwaysAndWhenInUseUsageDescription键。 along with other 2 keys.以及其他 2 个键。

This is issue with ios 8 Add this to your code这是 ios 8 的问题 将此添加到您的代码中

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

and to 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>

To Access User Location in iOS 8 you will have to add,要在 iOS 8 中访问用户位置,您必须添加,

NSLocationAlwaysUsageDescription in the Info.plist 

This will ask the user for the permission to get their current location.这将要求用户获得获取其当前位置的权限。

Objective-C Procedure Follow the below instructions: Objective-C 过程遵循以下说明:

For iOS-11 For iOS 11 have a look at this Answer: iOS 11 location access对于 iOS-11对于 iOS 11,请查看此答案: iOS 11 位置访问

Need to Add two Keys into plist and provide message as below image:需要将两个密钥添加到 plist 并提供如下图所示的消息:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

在此处输入图片说明 For iOS-10 and below:对于 iOS-10 及以下:

NSLocationWhenInUseUsageDescription

在此处输入图片说明

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

Delegate Methods委托方法

#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快速程序

Follow the below instructions:请按照以下说明操作:

For iOS-11 For iOS 11 have a look at this Answer: iOS 11 location access对于 iOS-11对于 iOS 11,请查看此答案: iOS 11 位置访问

Need to Add two Keys into plist and provide message as below image:需要将两个密钥添加到 plist 并提供如下图所示的消息:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

在此处输入图片说明 For iOS-10 and below:对于 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()
    }
}

Delegate Methods委托方法

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

}

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

A little helper for all of you that have more than one Info.plist file...对拥有多个 Info.plist 文件的所有人的小帮手...

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

It will add the needed tag to all of the Info.plist files in the current directory (and subfolders).它会将所需的标签添加到当前目录(和子文件夹)中的所有 Info.plist 文件中。

Another is:另一个是:

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

It will add your description to all files.它会将您的描述添加到所有文件中。

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

}

I get a similar error in iOS9 (working with Xcode 7 and Swift 2): Trying to start MapKit location updates without prompting for location authorization.我在 iOS9 中遇到了类似的错误(使用 Xcode 7 和 Swift 2):尝试在不提示位置授权的情况下启动 MapKit 位置更新。 Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.必须先调用 -[CLLocationManager requestWhenInUseAuthorization] 或 -[CLLocationManager requestAlwaysAuthorization]。 I was following a tutorial but the tutor was using iOS8 and Swift 1.2.我正在学习教程,但导师使用的是 iOS8 和 Swift 1.2。 There are some changes in Xcode 7 and Swift 2, I found this code and it works fine for me (if somebody needs help):在 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)
    }
}

Finally, I put that in info.plist: Information Property List: NSLocationWhenInUseUsageDescription Value: App needs location servers for staff最后,我把它放在 info.plist 中:信息属性列表: NSLocationWhenInUseUsageDescription值:应用程序需要员工的位置服务器

In order to access the users location in iOS.为了访问用户在 iOS 中的位置。 You need to add two keys你需要添加两个键

NSLocationWhenInUseUsageDescription NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription NSLocationAlwaysUsageDescription

into the Info.plist file.进入 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>

See this below image.请参阅下图。

Info.plist 图像

  1. Add key NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription (background GPS use) with string asking to use GPS on each info.plist from each target.添加键NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription (背景 GPS 使用)和字符串,要求在每个目标的每个info.plist上使用 GPS。

  2. Ask for permission by running:通过运行请求许可:

    [self initLocationManager:locationManager]; [self initLocationManager:locationManager];

Where initLocationManager is: initLocationManager在哪里:

// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{

    locationManager = [[CLLocationManager alloc]init];

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

Remember that if the keys are not on each info.plist for each target the app will not ask the user.请记住,如果密钥不在每个目标的每个info.plist ,应用程序将不会询问用户。 The if provides compatibility with iOS 7 and the respondsToSelector: method guarantees future compatibility rather than just solving the issue for iOS 7 and 8. if提供与 iOS 7 的兼容性, respondsToSelector:方法保证了未来的兼容性,而不仅仅是解决 iOS 7 和 8 的问题。

The problem for me was that the class that was the CLLocationManagerDelegate was private, which prevented all the delegate methods from being called.我的问题是CLLocationManagerDelegate类是私有的,这阻止了所有委托方法被调用。 Guess it's not a very common situation but thought I'd mention it in case t helps anyone.猜猜这不是一个很常见的情况,但我想我会提到它以防对任何人有帮助。

I add those key in InfoPlist.strings in iOS 8.4, iPad mini 2. It works too.我在iOS 8.4、iPad mini 2 的InfoPlist.strings中添加了这些键它也能工作。 I don't set any key, like NSLocationWhenInUseUsageDescription , in my Info.plist .我没有在我的Info.plist设置任何键,比如NSLocationWhenInUseUsageDescription


InfoPlist.strings : InfoPlist.strings

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

Base on this thread , it said, as in iOS 7 , can be localized in the InfoPlist.strings.它说, 基于这个线程as in iOS 7 ,可以在 InfoPlist.strings 中进行本地化。 In my test, those keys can be configured directly in the file InfoPlist.strings .在我的测试中,这些键可以直接在文件InfoPlist.strings配置。

So the first thing you need to do is to add one or both of the > following keys to your Info.plist file:因此,您需要做的第一件事是将 > 以下键中的一个或两个添加到您的 Info.plist 文件中:

  • NSLocationWhenInUseUsageDescription NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription NSLocationAlwaysUsageDescription

Both of these keys take a string which is a description of why you need location services.这两个键都采用一个字符串,它描述了您为什么需要位置服务。 You can enter a string like “Location is required to find out where you are” which, as in iOS 7 , can be localized in the InfoPlist.strings file.您可以输入类似“Location is required to find your where you are”这样的字符串,就像在iOS 7 中一样,可以在 InfoPlist.strings 文件中进行本地化。


UPDATE:更新:

I think @IOS 's method is better.我认为@IOS的方法更好。 Add key to Info.plist with empty value and add localized strings to InfoPlist.strings .使用空值向Info.plist添加键,并将本地化字符串添加到InfoPlist.strings

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM