【问题标题】:iOS 8 Map Kit Obj-C Cannot Get Users LocationiOS 8 Mapkit Objc 无法获取用户位置
【发布时间】:2014-09-03 05:58:18
【问题描述】:

我正在使用 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];

迈克。

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

【问题讨论】:

  • 我也无法让 cl 正常工作。有了这个测试版(感觉是 alpha),如果它在 ios7 上运行,我认为你不应该受到责备
  • 第 N 次:您不应期望 locationManager.location 在调用 startUpdatingLocation 后立即始终具有有效值。您必须实现 didUpdateLocations 委托方法并在那里处理位置。不要忘记将 locationManager.delegate 设置为 self ,否则不会调用委托方法。

标签: objective-c mapkit cllocationmanager ios8


【解决方案1】:

实际上,我正在学习 CS193P Lecture 16,这是关于位置和地图视图的,我无法让位置管理器在 iOS 8 中工作,应用视频中的内容。 看看你的回答,我可以让它工作。

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

在 AddPhotoViewController.hn 中添加了定义:

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

【讨论】:

  • viewDidLoad中会调用locationManager的getter。这个 getter 做了:locationManager alloc init,locationManager.delegate = self,将 locationManager.desiredAccuracy 设置为 kCLLocationAccuracyBest。
  • 不要使用IS_OS_8_OR_LATER 宏。有适当的方法可以得到一个方法是否可以使用。
【解决方案2】:

要扩展已接受的答案,并且如果您创建一个仅具有上述功能的示例项目,那么除了 CoreLocationMapkit 框架之外,您可能需要添加 UIKitFoundationCoreGraphics 框架手动以及Xcode 6

【讨论】:

    【解决方案3】:

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

    这是让 MapKit 地图视图在 iOS 8 中工作的完整代码。

    在您的 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];
    }
    

    享受吧!

    --麦克

    【讨论】:

    • @MBarton 之前的 ios 8 对我来说已经足够了 uimapkit.showsUserLocation = YES;和 mapkit 代表。现在在 ios 8 中,我应该声明 CLLocationManager 来请求足够的自动化吗?或者有没有办法强制mapkit请求足够的权限?
    • 你是怎么得到这些东西的?
    • @nyekimov 据我所知,您需要调用 CLLocationManager 来请求授权。
    • @nyekimov 你有没有找到在 mapViews locationManager 上调用 requestAlwaysAuthorization 的方法,而不必自己创建 locationManager 实例?我确信有一种方法可以为 MKMapViews 正确执行此操作。
    • 不需要IS_IOS_8_OR_LATER 宏。只需检查requestWhenInUseAuthorization(或requestAlwaysAuthorization)方法是否存在。
    【解决方案4】:

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

    NSLocationWhenInUseUsageDescription
    

    NSLocationAlwaysUsageDescription
    

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

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

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

    【讨论】:

      【解决方案5】:

      它没有写在任何地方,但是如果您的应用程序以 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");
      }
      

      【讨论】:

      • 这是个好主意。或者您在设置mapView.showsUserLocation = YES 之前检查[CLLocationManager authorizationStatus]。这也有助于消除警告。
      • 你不需要那个额外的控制器,在请求身份验证并添加 plist 密钥后消息消失。
      • 用户响应授权请求后消失。因此,在第二次使用该应用程序时,该消息不再出现。但是在第一次,当用户没有回复时,消息一直出现。
      • 在设置 mapView.showsUserLocation = YES 之前检查 [CLLocationManager authorizationStatus] 也是不够的。我相信如果您只声明一个 CLLocation 类型的强变量,就会触发该消息。但我同意创建视图控制器只是为了避免这种情况是矫枉过正的。感谢 Sebastian Wramba 和 @Ven 的贡献
      【解决方案6】:

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

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

      【讨论】:

      • 他在这些调用的正上方发表了评论,选择一个,而不是两个都调用。
      • 自从我发帖后就对其进行了编辑.. 可能是为了添加该评论。它最初肯定不存在。
      • 我在datacalculation.blogspot.in/2014/11/…找到了一个初学者级别的描述
      【解决方案7】:

      试试这个:

       (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
      
          if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
              self.mapView.showsUserLocation = YES;
          }
      

      【讨论】:

        【解决方案8】:

        您的代码看起来不错,尽管您不需要调用 requestWhenInUseAuthorization 和另一个 requestAlwaysAuthorization ,但请选择您需要的一个。

        显示位置的代码只是分配locationManager,不要期望立即获得位置数据。

        您需要等到委托方法被调用: -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
        ,那么 self.locationManager.location 也会被设置。

        【讨论】:

        猜你喜欢
        • 2015-01-20
        • 2015-03-05
        • 1970-01-01
        • 1970-01-01
        • 2014-12-10
        • 2016-04-22
        • 1970-01-01
        • 2014-10-26
        相关资源
        最近更新 更多