programar desde desarrollo cero apple aplicaciones ios gps core-location cllocationmanager

ios - desde - swift apple



iOS: la aplicaciĆ³n no solicita el permiso del usuario al instalar la aplicaciĆ³n. consiguiendo kCLAuthorizationStatusNotDeterminado cada vez-Objective-c & Swift (12)

Estoy intentando buscar la ubicación del usuario en mi aplicación iOS. He incluido el framework de ubicación de corelocation en mi proyecto primero. Luego, en un botón, haga clic en Invocar la API de ubicación central que se muestra a continuación. Cuando intento instalar esto en un dispositivo, la ubicación central nunca solicita permiso al usuario. Cuando trato de buscar la ubicación con el clic del botón, obtengo kCLAuthorizationStatusNotDetermined como authorisationStatus. Por favor, ayúdame en esto. No tengo idea de lo que está pasando.

- (IBAction)fetchLessAccurateLocation:(id)sender { [self.txtLocation setText:@""]; locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; locationManager.distanceFilter = 1000; if ([self shouldFetchUserLocation]) { [locationManager startUpdatingLocation]; } }

Este es mi método shouldFetchUserLocation:

-(BOOL)shouldFetchUserLocation{ BOOL shouldFetchLocation= NO; if ([CLLocationManager locationServicesEnabled]) { switch ([CLLocationManager authorizationStatus]) { case kCLAuthorizationStatusAuthorized: shouldFetchLocation= YES; break; case kCLAuthorizationStatusDenied: { UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"App level settings has been denied" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } break; case kCLAuthorizationStatusNotDetermined: { UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The user is yet to provide the permission" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } break; case kCLAuthorizationStatusRestricted: { UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The app is recstricted from using location services." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } break; default: break; } } else{ UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The location services seems to be disabled from the settings." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } return shouldFetchLocation; }

Aquí está mi método central de delegado de ubicación:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0){ NSLog(@"location fetched in delegate"); CLLocation* location = [locations lastObject]; NSDate* eventDate = location.timestamp; NSTimeInterval howRecent = [eventDate timeIntervalSinceNow]; if (abs(howRecent) < 15.0) { // If the event is recent, do something with it. NSLog(@"inside loop.... latitude %+.6f, longitude %+.6f/n", location.coordinate.latitude, location.coordinate.longitude); } NSLog(@"latitude %+.6f, longitude %+.6f/n", location.coordinate.latitude, location.coordinate.longitude); [self.txtLocation setText:[NSString stringWithFormat:@"/nlatitude: %+.6f /nlongitude: %+.6f", location.coordinate.latitude, location.coordinate.longitude]]; [locationManager stopUpdatingLocation]; [locationManager stopMonitoringSignificantLocationChanges]; if(locationManager!=nil){ locationManager.delegate= nil; locationManager= nil; } }


iOS8 nos tiene grandes cambios de API con los LocationsServices

Suponiendo que [CLLocationManager locationServicesEnabled] devuelva SÍ,

Con el primer lanzamiento de la aplicación iOS [iOS7 e iOS8] - locationMangers (CLLocationManager) authorizationStatus preestablecido para

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

Prompting en iOS7 +

Inicie el locationManger (CLLocationManager, Strong) y configure los delegados (CLLocationManagerDelegate)

Ahora, para solicitar al usuario que use los Servicios de ubicación y la Lista de la aplicación en Configuración> Privacidad> Servicios de ubicación, DEBE llamar a cualquiera de los métodos de servicios de ubicación, depende del requisito de la aplicación; por ejemplo, si la aplicación es una de las siguientes.

Actualizaciones de ubicaciones - [self.locationManager startUpdatingLocation]

RegionMonitoring - [self.locationManager startMonitoringForRegion:beaconRegion]

Inmediatamente después de las ejecuciones del método anterior, iOS solicitará al usuario que solicite aceptar el uso de los Servicios de ubicación en la aplicación y, independientemente de la aplicación de elección del usuario, se enumerará en Configuración> Privacidad> Servicios de ubicación.

Preguntar en iOS8 +

Es en el mismo caso con iOS8, con el primer lanzamiento de los Servicios de ubicación de la aplicación

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

iOS 8 tenemos nuevos métodos para mostrar el aviso al usuario

[self.locationManager requestAlwaysAuthorization] or [self.locationManager requestWhenInUseAuthorization]

requestAlwaysAuthorization / requestWhenInUseAuthorization disponible de iOS8. si el destino de la implementación de la aplicación es iOS7, envuelva esto en bloque para asegurarse de que en iOS7 esto no provoque el bloqueo de la aplicación.

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

o

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

Muy importante ###:

Según iOS8 es obligatorio incluir la cadena que indica por qué la aplicación utiliza requestAlwaysAuthorization / requestWhenInUseAuthorization en info.plist incluye cualquiera de estas propiedades en relación con el requisito de la aplicación

para kCLAuthorizationStatusAuthorizedSiempre incluye clave / valor (valor de cadena) par

NSLocationAlwaysUsageDescription = App use Locations service mode Always

para kCLAuthorizationStatusAuthorizedWhenInUse include clave / valor (valor de cadena) par

NSLocationWhenInUseUsageDescription = App use Locations service mode In Use

Captura de pantalla de info.plist (en caso de que alguien esté confundido por esto)


Cuando solicite la ubicación, no debe olvidar esas cosas (iOS 8+):

  1. Agregue este indicador en su info.plist de la aplicación: NSLocationAlwaysUsageDescription o NSLocationWhenInUseUsageDescription dependen si siempre quiere acceder a la ubicación o solo cuando la aplicación está en uso (la segunda se recomienda si no necesita acceder siempre). Esto es lo más importante porque es nuevo y extraño.
  2. Si solicita permiso siempre, no se olvide de agregar actualizaciones de ubicación como modo de fondo en sus capacidades de destino
  3. Asegúrese de solicitar el permiso correcto al inicializar el administrador de ubicación:

    -(void)initLocationManager{ locationManager = [[CLLocationManager alloc] init]; locationManager.delegate=self; [locationManager requestAlwaysAuthorization]; // HERE ASK FOR THE RELEVANT }

Para probar en el simulador, le sugiero que "Restablezca todo el contenido y la configuración" de sus opciones. Esa es la única forma de obtener exactamente la misma experiencia que obtendría un nuevo usuario de la aplicación.


Debe tener NSLocationWhenInUseUsageDescription agregado a su info.plist . Es un poco raro, pero solo agrégalo como un valor de cadena sin texto y luego cuando quieras que la ubicación comience con:

CLLocationManager * locationManager = [[CLLocationManager alloc] init]; [locationManager requestWhenInUseAuthorization];


Desinstala la aplicación e intenta ejecutarla nuevamente.

Si no funcionó, ve a la configuración y deshabilita la autorización para esa aplicación. Después de eso ejecutarlo de nuevo para ver si pide permisos.

O:

Puede forzar a la aplicación a comenzar a monitorear la ubicación con un código como ese:

self.locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyBest; [locationManager startUpdatingLocation];

en sus métodos de delegado puede detectar si hay un error al obtener la ubicación y puede informar al usuario.

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { // Delegate of the location manager, when you have an error NSLog(@"didFailWithError: %@", error); UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"application_name", nil) message:NSLocalizedString(@"location_error", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles:nil]; [errorAlert show]; }

Si tiene alguna pregunta dígame.


En iOS 8, debe hacer dos cosas adicionales para que la ubicación funcione: agregue una clave a su Info.plist y solicite autorización al administrador de ubicación para que comience. Hay dos claves Info.plist para la nueva autorización de ubicación. Se requiere una o ambas de estas claves. Si ninguna de las claves está allí, puede llamar a startUpdatingLocation, pero el administrador de ubicación no se iniciará realmente. Tampoco enviará un mensaje de error al delegado (dado que nunca se inició, no puede fallar). También fallará si agrega una o ambas claves pero olvida solicitar explícitamente la autorización.

Entonces, lo primero que debe hacer es agregar una o ambas de las siguientes claves a su archivo Info.plist:

NSLocationWhenInUseUsageDescription NSLocationAlwaysUsageDescription

Ambas claves toman una cadena que es una descripción de por qué necesita servicios de ubicación. Puede ingresar una cadena como "Se requiere una ubicación para averiguar dónde se encuentra" que, como en iOS 7, se puede localizar en el archivo InfoPlist.strings.

A continuación, debe solicitar autorización para el método de ubicación correspondiente, WhenInUse o Background. Use una de estas llamadas:

[self.locationManager requestWhenInUseAuthorization] [self.locationManager requestAlwaysAuthorization]

Para article


Estaba enfrentando el mismo problema, luego de volver a instalar mi aplicación, devolvía kCLAuthorizationStatusNotDetermined siempre que [CLLocationManager authorizationStatus] y la aplicación ni siquiera aparecía en Settings> Privacy> Location Services.

El diálogo de autorización que iOS solicita al usuario para que apruebe el acceso a los servicios de ubicación se desencadena en [locationManager startUpdatingLocation] que en su caso nunca se llama ( shouldFetchUserLocation siempre será NO ).

La solución de Miguel C. parece una buena solución, intentará eso.

Editar para iOS8.x

Cuando vino iOS8 trajo pocos cambios en la forma en que se usa CLLocationManager. Como mencioné algunas veces en otras respuestas, requiere un paso adicional en comparación con iOS7. Hoy me enfrenté al problema yo mismo y encontré este article (ha sido referenciado de muchas otras preguntas pero completa mi respuesta anterior). ¡Espero eso ayude!


He tenido el problema que Rashmi Ranjan Mallick dijo en los comentarios pocas veces desde que se lanzó iOS 7. Realmente creo que es un error de iOS 7, tienen un montón de ellos en la nueva versión de iOS.

Para mí, el problema fue el mismo:

1. Abra la aplicación, nunca se le preguntó acerca de la ubicación. iOS no estaba preguntando sobre permissons
2. Fui a Configuración-> Privacidad-> Servicios de ubicación y mi aplicación no estaba allí.
3. No pude cambiar los permisos de ubicación de mi aplicación de ninguna manera.

Una solución para eso es:

1. Mata tu aplicación.
2. Deshabilitar todos los servicios de ubicación con el botón principal del interruptor.
3.Vuelve a tu aplicación nuevamente.
4. Mata tu aplicación.
5. Habilitar los servicios de ubicación nuevamente en el botón de cambio anterior.
6.Si aún no aparece en la lista, vuelve a acceder a tu aplicación, mátalo nuevamente y vuelve a la configuración.
7. Ahora debería estar allí.

Esto funcionó para mí y espero que esto sea útil.

ACTUALIZACIÓN: si iOS 8, asegúrese de llamar a requestWhenInUseAuthorization o requestAlwaysAuthorization

Puedes seguir este código: :)

#ifdef __IPHONE_8_0 if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { if([[Wave_SettingsObject sharedObject] backgroundLocationEnabled].boolValue == YES) { if(![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) { NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription key"); } if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) //iOS 8+ { [locationManager requestAlwaysAuthorization]; } } else if([[Wave_SettingsObject sharedObject] isLocationEnabled].boolValue == YES) { if(![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) { NSLog(@"Info.plist does not contain NSLocationWhenInUseUsageDescription key"); } if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) //iOS 8+ { [locationManager requestWhenInUseAuthorization]; } } } #endif


Me encontré con este problema, implementé todas las cosas necesarias, incluidas las claves pList y mi aplicación todavía no solicitaba la ubicación.

Resulta que el problema era que la variable locationManager no puede ser local, necesita ser una variable de instancia.

Entonces, en lugar de

-(void) updateLocation { CLLocationManager *locationManager = ... }

Necesita ser:

CLLocationManager *locationManager; -(void) updateLocation { self.locationManager = ... }


Prueba agregar

[locationManager startUpdatingLocation]

también asegúrese de que los servicios de localización estén activados.

EDITAR:

También intente eliminar la aplicación y volver a instalarla. Puede haber un registro de que la aplicación está leyendo, lo que impide que solicite permiso para usar la ubicación.


Si enfrenta este problema en iOS8, use : requestWhenInUseAuthorization.


Tuve un problema similar, pero fue causado por una razón diferente. Agregándolo aquí en caso de que pueda ayudar a alguien más.

Dejé de recibir el mensaje de solicitud de autorización, y como estaba funcionando antes de que los requisitos descritos en las otras respuestas ya se hayan cumplido: la clave en el plist, verificando el estado de la autorización y luego solicitando permiso en ios8 +.

En mi caso, el problema estaba relacionado con el modo "Guía de acceso". Esta es una aplicación para un kiosco, y solo comienza a balizas de alcance una vez que se activa "Guía de acceso". Pero parece que los mensajes de solicitud de autorización no se envían en este modo. Podría arreglarlo simplemente moviendo el procedimiento de solicitud de autorización al DidLoad de la primera vista mostrada.

Lo mismo sucede con la solicitud de usar la cámara.


Objective-C Sigue las instrucciones a continuación:

iOS-11 para iOS 11 eche un vistazo a esta respuesta: acceso a la ubicación de iOS 11

Es necesario agregar dos teclas en el plist y proporcionar el mensaje como se muestra a continuación:

1. NSLocationAlwaysAndWhenInUseUsageDescription 2. NSLocationWhenInUseUsageDescription

iOS-10 y abajo:

NSLocationWhenInUseUsageDescription

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

Métodos Delegat

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

código SWIFT

Siga las siguientes instrucciones:

iOS-11 para iOS 11 eche un vistazo a esta respuesta: acceso a la ubicación de iOS 11

Es necesario agregar dos teclas en el plist y proporcionar el mensaje como se muestra a continuación:

1. NSLocationAlwaysAndWhenInUseUsageDescription 2. NSLocationWhenInUseUsageDescription

iOS-10 y abajo:

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() } }

Delegar métodos

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