objective-c mapkit cllocationmanager ios8

objective c - iOS 8 Map Kit Obj-C no puede obtener ubicación de los usuarios



objective-c mapkit (8)

Estoy trabajando con Map Kit en iOS 8 usando Obj-C NOT SWIFT. No puedo obtener la ubicación del dispositivo, está configurado en 0.00, 0.00 y recibo el error:

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

Implementé: (He intentado solo uno a la vez y no tuve suerte)

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

Y en info.plist

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

Me solicitan que permita que la aplicación use mi ubicación, pero después de que estoy de acuerdo, nada cambia. La ubicación se muestra como 0.00, 0.00.

Código para mostrar la ubicación de los usuarios:

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

Micro.

** EDITAR: Ver respuesta a continuación.


Además de la respuesta de Mikes, descubrí que usar ambos [self.locationManager requestWhenInUseAuthorization]; y [self.locationManager requestAlwaysAuthorization]; como se demuestra en su código no funciona. Solo deberías usar UNO .

Supongo que se realizaron algunos cambios adicionales con una versión más reciente / estable de la API.


De hecho, estoy estudiando CS193P Lecture 16, que trata sobre la ubicación y la vista del mapa, y no pude hacer que el administrador de ubicación funcione en iOS 8, aplicando lo que estaba en el video. Mirando tu respuesta, podría hacerlo funcionar.

El Info.plist fue modificado como se describe en las respuestas (yo uso NSLocationWhenInUseUsageDescription).

En AddPhotoViewController.hn se agregó la definición:

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

En AddPhotoViewController.m, se agregó el siguiente código en ViewDidLoad (después de self.image):

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

La autorización se solicitará solo una vez, la primera vez que inicie la aplicación.

Lo siguiente también se agregó a AddPhotoViewController.h porque no se dijo en la lección 16:

@property (nonatomic) NSInteger locationErrorCode;

shouldPerformSegueWithIdentifier se modificó para incluir 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 fue agregado:

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


Lo tengo funcionando. He publicado mi código a continuación para ayudar a cualquier otra persona que tenga problemas.

Aquí está mi código completo para que MapKit Map View funcione en iOS 8.

En AppName- Info.plist, agregue una nueva fila con el nombre de la clave:

NSLocationWhenInUseUsageDescription

O

NSLocationAlwaysUsageDescription

Con el valor que es una cadena del mensaje que desea que se muestre:

YourAppName would like to use your location.

En tu archivo de encabezado (Utilizo App Name -Prefix.pch pero YourViewController.h también funcionará)

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

¡Disfrutar!

--Micro


No está escrito en ningún lado, pero si su aplicación comienza con MapKit, igual recibirá el mensaje de error "Intentando iniciar las actualizaciones de ubicación de MapKit sin solicitar autorización de ubicación" incluso después de implementar la respuesta de MBarton. Para evitarlo, debe crear un nuevo controlador de vista antes del MapKit e implementar allí los delegados del administrador de ubicación. Lo llamé AuthorizationController.

Entonces, en AuthorizationController.h:

#import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> @interface MCIAuthorizationController : UIViewController <CLLocationManagerDelegate> @property (strong, nonatomic) CLLocationManager *locationManager; @end

Y en 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"); }


Para ampliar la respuesta aceptada, y si crea un proyecto de muestra con la funcionalidad anterior, entonces, aparte de los CoreLocation y Mapkit , es posible que necesite agregar manualmente el marco UIKit , Foundation y UIKit en Xcode 6 .


Prueba este:

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


Su código se ve bien, aunque no necesita llamar a requestWhenInUseAuthorization y la otra requestAlwaysAuthorization, elija la que necesite.

El código para mostrar ubicaciones aún está asignando locationManager, no espere obtener datos de ubicación instantáneamente.

debe esperar a que se llame al método de delegado: -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
, también se establecerá self.locationManager.location.


Tuve el mismo problema pero al agregar estas dos líneas en un archivo plist resolví mis problemas

NSLocationWhenInUseUsageDescription

Y

NSLocationAlwaysUsageDescription

NOTA: debe proporcionar una descripción de cadena de estos dos valores. Puede usar cualquiera de ellos en su archivo controlador como se muestra a continuación

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

Debe implementar CLLOcationManagerDelegate en su controlador para acceder a esta funcionalidad