iOS 8 Mapkit Objc无法获取用户位置

时间:2014-07-12 21:36:56

标签: objective-c mapkit cllocationmanager ios8

我使用Obj-C NOT SWIFT在iOS 8中使用Map Kit。我无法获得它设置的设备位置0.00,0.00,我收到错误:

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

我已经实施了:(我一次只试过一次但没有运气)

if(IS_OS_8_OR_LATER) {
    [self.locationManager requestWhenInUseAuthorization];
    [self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation]; 

并在info.plist

NSLocationWhenInUseUsageDescription  :   App would like to use your location.
NSLocationAlwaysUsageDescription  :  App would like to use your location.

我会收到提示,允许该应用使用我的位置,但在我同意之后没有任何变化。该位置显示为0.00,0.00。

显示用户位置的代码:

//Get Location
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];

MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = self.locationManager.location.coordinate.latitude;
region.center.longitude = self.locationManager.location.coordinate.longitude;
region.span.longitudeDelta = 0.005f;
region.span.longitudeDelta = 0.005f;
[mapView setRegion:region animated:YES];

麦克

**编辑:查看下面的答案。

8 个答案:

答案 0 :(得分:130)

我得到了它的工作。我在下面发布了我的代码,以帮助其他人遇到问题。

这是我在iOS 8中使用MapKit Map View的完整代码。

AppName -Info.plist中 添加一个键名为:

的新行
NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

值为您要显示的消息的字符串:

YourAppName would like to use your location.

在头文件中。 (我使用 App Name -Prefix.pch但是YourViewController.h也可以使用)

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

YourViewController.h

#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>

@interface YourViewController : UIViewController <MKMapViewDelegate,  CLLocationManagerDelegate> {

}


@property(nonatomic, retain) IBOutlet MKMapView *mapView;
@property(nonatomic, retain) CLLocationManager *locationManager;

YourViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.


    mapView.delegate = self;
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    #ifdef __IPHONE_8_0
    if(IS_OS_8_OR_LATER) {
         // Use one or the other, not both. Depending on what you put in info.plist
        [self.locationManager requestWhenInUseAuthorization];
        [self.locationManager requestAlwaysAuthorization];
    }
    #endif
    [self.locationManager startUpdatingLocation];

    mapView.showsUserLocation = YES;
    [mapView setMapType:MKMapTypeStandard];
    [mapView setZoomEnabled:YES];
    [mapView setScrollEnabled:YES];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:YES];

    self.locationManager.distanceFilter = kCLDistanceFilterNone;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [self.locationManager startUpdatingLocation];
    NSLog(@"%@", [self deviceLocation]);

    //View Area
    MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
    region.center.latitude = self.locationManager.location.coordinate.latitude;
    region.center.longitude = self.locationManager.location.coordinate.longitude;
    region.span.longitudeDelta = 0.005f;
    region.span.longitudeDelta = 0.005f;
    [mapView setRegion:region animated:YES];

}

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
    [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
- (NSString *)deviceLocation {
    return [NSString stringWithFormat:@"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceLat {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.coordinate.latitude];
}
- (NSString *)deviceLon {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceAlt {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.altitude];
}

享受!

- 麦克

答案 1 :(得分:8)

它不会写在任何地方,但如果您的应用程序以MapKit开头,即使在实施MBarton的答案后,您仍会收到错误消息“尝试启动MapKit位置更新而不提示位置授权”。要避免它,您必须在MapKit之前创建一个新的视图控制器,并在那里实现位置管理器委托。我称之为AuthorizationController。

所以,在AuthorizationController.h中:

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface MCIAuthorizationController : UIViewController <CLLocationManagerDelegate>

@property (strong, nonatomic) CLLocationManager *locationManager;

@end

在AuthorizationController.m中:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Location manager
    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];
    }
}

#pragma mark - Location Manager delegates

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    NSLog(@"didUpdateLocations: %@", [locations lastObject]);
}


- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"Location manager error: %@", error.localizedDescription);
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        [self.locationManager startUpdatingLocation];
        [self performSegueWithIdentifier:@"startSegue" sender:self];
    } else if (status == kCLAuthorizationStatusDenied) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location services not authorized"
                                                        message:@"This app needs you to authorize locations services to work."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    } else
        NSLog(@"Wrong location status");
}

答案 2 :(得分:3)

试试这个:

 (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {

    if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        self.mapView.showsUserLocation = YES;
    }

答案 3 :(得分:2)

您的代码看起来很好,但您不需要调用requestWhenInUseAuthorization和其他requestAlwaysAuthorization,请选择您需要的代码。

显示位置的代码尚未分配locationManager,不希望立即获取位置数据。

你需要等到调用委托方法: -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
,然后也将设置self.locationManager.location。

答案 4 :(得分:2)

对于Mikes的回答,我发现使用 [self.locationManager requestWhenInUseAuthorization];[self.locationManager requestAlwaysAuthorization];,如他的代码所示,不起作用。您应该只使用 ONE

我假设使用更新/稳定版本的API进行了一些进一步的更改。

答案 5 :(得分:2)

我遇到了同样的问题,但在plist文件中添加这两行解决了我的问题

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

注意:必须提供这两个值的字符串描述。您可以在控制器文件中使用它们中的任何一个,如下所示

self.locationManager= [[CLLocationManager alloc] init];
self.locationManager.delegate=self;
[self.locationManager requestAlwaysAuthorization];

您必须在控制器中实施CLLOcationManagerDelegate才能访问此功能

答案 6 :(得分:0)

要扩展已接受的答案,如果您使用上述功能创建示例项目,那么除了CoreLocationMapkit框架之外,您可能需要添加UIKit,{{ 1}}和Foundation框架也可以在CoreGraphics中手动完成。

答案 7 :(得分:-2)

实际上,我正在研究CS193P第16讲,这是关于位置和地图视图,我无法使位置管理器在iOS 8中工作,应用视频中的内容。 看看你的答案,我可以让它发挥作用。

Info.plist已按照答案中的描述进行了修改(我使用了NSLocationWhenInUseUsageDescription)。

在AddPhotoViewController.hn中添加了define:

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

在AddPhotoViewController.m中,ViewDidLoad中添加了以下代码(在self.image之后):

#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER)
{
    [self.locationManager requestWhenInUseAuthorization];
}
#endif

首次启动应用程序时,只会询问一次授权。

以下内容也被添加到AddPhotoViewController.h中,因为它没有在第16讲中说明:

@property (nonatomic) NSInteger locationErrorCode;

shouldPerformSegueWithIdentifier被修改为包含else if(!self.location):

else if (![self.titleTextField.text length])
        {
            [self alert:@"Title required"];
            return NO;
        }
        else if (!self.location)
        {
            switch (self.locationErrorCode)
            {
                case kCLErrorLocationUnknown:
                    [self alert:@"Couldn't figure out where this photo was taken (yet)."]; break;
                case kCLErrorDenied:
                    [self alert:@"Location Services disabled under Privacy in Settings application."]; break;
                case kCLErrorNetwork:
                    [self alert:@"Can't figure out where this photo is being taken.  Verify your connection to the network."]; break;
                default:
                    [self alert:@"Cant figure out where this photo is being taken, sorry."]; break;
            }
            return NO;
        }
        else
        { // should check imageURL too to be sure we could write the file
            return YES;
        }

添加了didFailWithError:

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    self.locationErrorCode = error.code;
}