objective-c iOS 8 Map Kit Obj-C 无法获取用户位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24717547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS 8 Map Kit Obj-C Cannot Get Users Location
提问by MBarton
I am working with Map Kit in iOS 8 using Obj-C NOT SWIFT. I cannot get the device location it is set a 0.00, 0.00 and I am getting the error:
我正在使用 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.
I have implemented: ( I have tried only one at a time and no luck )
我已经实施了:(我一次只尝试了一个,但没有运气)
if(IS_OS_8_OR_LATER) {
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
And in info.plist
在 info.plist 中
NSLocationWhenInUseUsageDescription : App would like to use your location.
NSLocationAlwaysUsageDescription : App would like to use your location.
I do get prompted to allow the app to use my location but after I agree nothing changes. The location is being showed as 0.00, 0.00.
我确实被提示允许应用程序使用我的位置,但在我同意之后没有任何变化。该位置显示为 0.00, 0.00。
Code for displaying users location:
显示用户位置的代码:
//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];
Mike.
麦克风。
**EDIT: View Answer Below.
**编辑:查看下面的答案。
回答by MBarton
I got it working. I've posted my code below to help anyone else having issues.
我让它工作了。我已经在下面发布了我的代码以帮助其他有问题的人。
Here is my full code to get the MapKit Map View working in iOS 8.
这是我让 MapKit 地图视图在 iOS 8 中工作的完整代码。
In your AppName-Info.plist Add a new row with the key name being:
在您的AppName-Info.plist 中添加一个新行,其键名是:
NSLocationWhenInUseUsageDescription
Or
或者
NSLocationAlwaysUsageDescription
With the value being a string of the message that you want to be displayed:
值是要显示的消息字符串:
YourAppName would like to use your location.
In your header file. (I use App Name-Prefix.pch but YourViewController.h will work too)
在你的头文件中。(我使用App Name-Prefix.pch 但 YourViewController.h 也可以使用)
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
YourViewController.h
你的视图控制器.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
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];
}
Enjoy!
享受!
--Mike
- 麦克风
回答by Rodrigo Pinto
It's not written anywhere, but if your app starts with MapKit, you will still receive the error message "Trying to start MapKit location updates without prompting for location authorization" even after implementing MBarton's answer. To avoid it, you have to create a new view controller before the MapKit, and implement the location manager delegates there. I called it AuthorizationController.
它没有写在任何地方,但是如果您的应用程序以 MapKit 启动,即使在实施 MBarton 的答案之后,您仍然会收到错误消息“尝试启动 MapKit 位置更新而不提示位置授权”。为了避免这种情况,您必须在 MapKit 之前创建一个新的视图控制器,并在那里实现位置管理器委托。我称之为 AuthorizationController。
So, in AuthorizationController.h:
因此,在 AuthorizationController.h 中:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface MCIAuthorizationController : UIViewController <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@end
And in AuthorizationController.m:
在 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");
}
回答by brusnikin
Try This One:
试试这个:
(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
self.mapView.showsUserLocation = YES;
}
回答by El Deanos Blanco
Further to Mikes answer, I found that using both[self.locationManager requestWhenInUseAuthorization];and [self.locationManager requestAlwaysAuthorization];as demonstrated in his code does not work. You should only use ONE.
继答案汗衫,我发现,使用两个[self.locationManager requestWhenInUseAuthorization];和[self.locationManager requestAlwaysAuthorization];在他的代码证明是行不通的。您应该只使用ONE。
I assume some further changes were made with a more recent/stable version of the API.
我假设使用更新/稳定版本的 API 进行了一些进一步的更改。
回答by PetrV
Your code looks fine, though you do not need to call requestWhenInUseAuthorization and the other requestAlwaysAuthorization , choose one you need.
您的代码看起来不错,但您不需要调用 requestWhenInUseAuthorization 和另一个 requestAlwaysAuthorization ,请选择您需要的一个。
Code for displaying locations is just yet allocating locationManager, do not expect to get location data instantly.
显示位置的代码只是在分配 locationManager,不要期望立即获得位置数据。
you need to wait till delegate method gets called :
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations, then self.locationManager.location will also be set.
您需要等到委托方法被调用 :
,然后 self.locationManager.location 也将被设置。-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
回答by Aadil Keshwani
I had the same problem but adding these two line in plist file solved my problems
我有同样的问题,但在 plist 文件中添加这两行解决了我的问题
NSLocationWhenInUseUsageDescription
And
和
NSLocationAlwaysUsageDescription
NOTE : Must provide string description of both these values. You can use any of them in your controller file as below
注意:必须提供这两个值的字符串描述。您可以在控制器文件中使用它们中的任何一个,如下所示
self.locationManager= [[CLLocationManager alloc] init];
self.locationManager.delegate=self;
[self.locationManager requestAlwaysAuthorization];
You must implement CLLOcationManagerDelegatein your controller to access this functionality
您必须CLLOcationManagerDelegate在控制器中实现才能访问此功能
回答by Deepak Thakur
To extend the accepted answer and if you create a sample project with just the above functionality, then apart from CoreLocationand Mapkitframeworks, you might need to add UIKit, Foundationand CoreGraphicsframework manually as well in Xcode 6.
为了扩大接受的答案,如果你创建一个示例项目,只是上面的功能,那么除了CoreLocation和Mapkit框架,你可能需要添加UIKit,Foundation和CoreGraphics手动框架,以及在Xcode 6。
回答by Vincent Cohen
Actually, I am studying the CS193P Lecture 16, which is about location and map view, and I could not make the location manager work in iOS 8, applying what was in the video. Looking at your answer, I could make it work.
实际上,我正在学习 CS193P Lecture 16,它是关于位置和地图视图的,我无法在 iOS 8 中使用位置管理器,应用视频中的内容。看着你的回答,我可以让它工作。
The Info.plist was modified as described in the answers (I use the NSLocationWhenInUseUsageDescription).
Info.plist 已按照答案中的描述进行修改(我使用 NSLocationWhenInUseUsageDescription)。
In AddPhotoViewController.hn the define was added :
在 AddPhotoViewController.hn 中添加了定义:
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
In AddPhotoViewController.m, the following code was added in ViewDidLoad (after self.image):
在 AddPhotoViewController.m 中,在 ViewDidLoad(self.image 之后)中添加了以下代码:
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER)
{
[self.locationManager requestWhenInUseAuthorization];
}
#endif
The authorization will be asked only once, the first time you launch the application.
授权只会在您第一次启动应用程序时询问一次。
The following was also added to AddPhotoViewController.h because it was not said in Lecture 16 :
AddPhotoViewController.h中还添加了以下内容,因为第16讲中没有说:
@property (nonatomic) NSInteger locationErrorCode;
shouldPerformSegueWithIdentifier was modified to include else if (!self.location) :
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 was added :
添加了 didFailWithError :
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
self.locationErrorCode = error.code;
}

