Los servicios de ubicación no funcionan en iOS 8

608

Mi aplicación que funcionó bien en iOS 7 no funciona con el SDK de iOS 8.

CLLocationManagerno devuelve una ubicación, y tampoco veo mi aplicación en Configuración -> Servicios de ubicación . Hice una búsqueda en Google sobre el tema, pero no surgió nada. ¿Qué podría estar mal?

özg
fuente
También puede usar esto como aplicación de referencia para la solución github.com/jbanford/ConstantLocationUpdates
ashok vadivelu
19
Publiqué sobre algunos de los cambios en el administrador de ubicación en iOS 8 aquí: nevan.net/2014/09/core-location-manager-changes-in-ios-8
nevan king
2
Podría intentar usar esta biblioteca que simplifica las API de ubicación central y expone una interfaz basada en bloques agradables y normaliza todas las diferencias entre las diferentes versiones de iOS ( Divulgación
lms
Encontré alguna referencia aquí datacalculation.blogspot.in/2014/11/…
Prueba de iOS
2
@nevanking usted señor! Necesito una corona! He estado luchando con este problema desde el cambio y todavía no he encontrado una "guía" sobre cómo solucionarlo, eso fue amigable para los novatos. Su guía hizo que un idiota como yo manejara el problema por mí mismo. Muchas gracias por ese enlace.
Patrick R

Respuestas:

1086

Terminé resolviendo mi propio problema.

Aparentemente, en iOS 8 SDK, requestAlwaysAuthorization(para la ubicación en segundo plano) o requestWhenInUseAuthorization(ubicación solo en primer plano) CLLocationManageres necesario llamar antes de comenzar las actualizaciones de ubicación.

También debe haber NSLocationAlwaysUsageDescriptiono NSLocationWhenInUseUsageDescriptioningresar Info.plistun mensaje para que se muestre en la solicitud. Agregar estos resolvió mi problema.

ingrese la descripción de la imagen aquí

Espero que ayude a alguien más.

EDITAR: Para obtener información más extensa, eche un vistazo a: Core-Location-Manager-Changes-in-ios-8

özg
fuente
66
¿puede compartir el valor exacto u actualizado en Info.plist? No puedo ver esa clave en mi Info.plist. Lo agregué y todavía no parece funcionar. Estoy usando Swift, iOS8 y XCode 6 beta 4
Vijay Kumar AB
44
@Vjay: debe editar el archivo Info.plist en un editor, no puede configurar esas claves en Xcode (a partir de la versión beta 6).
Kendall Helmstetter Gelner
11
Solo un recordatorio, si no desea mostrar una explicación personalizada al usuario, simplemente configure esta clave en una cadena vacía.
melive
77
Debe conservar su locationManager para que funcione. así que haga que su CLLocationManager sea una propiedad sólida
Vassily
273
ME ENCANTA que no reciba ningún error, ninguna advertencia, ningún mensaje de registro, NADA si deja de lado la entrada de la lista. Básicamente, Apple ha creado una llamada a la API que NO HACE NADA si no tiene la entrada de lista adecuada. Gracias a @OrtwinGentz ​​por resolver esto.
MobileVet
314

Me estaba arrancando el pelo con el mismo problema. Xcode te da el error:

Intentando iniciar MapKitactualizaciones de ubicación sin solicitar autorización de ubicación. Debe llamar -[CLLocationManager requestWhenInUseAuthorization]o -[CLLocationManager requestAlwaysAuthorization]primero.

Pero incluso si implementa uno de los métodos anteriores, no avisará al usuario a menos que haya una entrada en info.plist para NSLocationAlwaysUsageDescriptiono NSLocationWhenInUseUsageDescription.

Agregue las siguientes líneas a su info.plist donde los valores de cadena representan la razón por la que necesita acceder a la ubicación de los usuarios

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>

Creo que estas entradas pueden haber faltado desde que comencé este proyecto en Xcode 5. Supongo que Xcode 6 podría agregar entradas predeterminadas para estas claves, pero no lo he confirmado.

Puede encontrar más información sobre estas dos configuraciones aquí

Enrique
fuente
13
Xcode 6 no agrega estas claves por defecto, si la intención de poner en práctica CLLocationManager debe agregar manualmente
Wesley Smith
1
¡También tuve que agregarlos manualmente, no pude agregarlos a través de la vista RawValues ​​de info.plist en Xcode6!
Kendall Helmstetter Gelner
1
Busqué esto por siempre. Mi mensaje [CLLLocationManagerauthoristStatus] solo devolvía un valor de <nil>. Después de agregar las claves anteriores, comenzó a devolver las enumeraciones respectivas para la salida de los mensajes. Por lo que he encontrado, este es un error conocido de iOS 8, pero no pude encontrar nada en mi contexto durante años. Gracias mil!
MrOli3000
44
Me gusta el valor de cadena que pones
Chris Chen
1
El mensaje aparecerá como el sub-mensaje en la Alerta que pregunta si el usuario desea compartir su ubicación. Como tal, simplemente estar vacío (en blanco) parece tener más sentido en mi aplicación. Una explicación de por qué quieres usar la ubicación también tendría sentido. Sin embargo, NSLocationWhenInUseUsageDescription no se comportó como se esperaba para mí (es decir, siguió obteniendo permiso denegado, aunque el valor de retorno era correcto). NSLocationAlwaysUsageDescription funcionó bien.
arcady bob
104

Para asegurarse de que esto sea compatible con iOS 7, debe verificar si el usuario ejecuta iOS 8 o iOS 7. Por ejemplo:

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

//In ViewDidLoad
if(IS_OS_8_OR_LATER) {
   [self.locationManager requestAlwaysAuthorization];
}

[self.locationManager startUpdatingLocation];
JKoko
fuente
164
Una mejor manera que verificar la versión es verificar si el objeto tiene ese selector, por ejemplo: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
progrmr
1
Tuve problemas simplemente implementando la solución de @progrmr al construir en Xcode 5, ya que no sabe cuál es el requestAlwaysAuthorizationmétodo. Mi solución adicional era utilizar esta línea en el ifcomunicado en lugar de una llamada método normal: [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. Tal vez esto sea obvio para otras personas, pero me tomó un tiempo darme cuenta. Creo que es la solución correcta hasta que se lance el Xcode 6 final.
VinceFior
2
La solución correcta es construir con Xcode 6. Si está compilando con Xcode 5, no necesita solicitar autorización, es automático.
programa el
Puede que tengas un punto. Mi preocupación era que quería que mi código se compilara en Xcode 5 (aunque no funcionaría en iOS 8 a menos que se compilara en Xcode 6) mientras mi equipo realiza la transición a Xcode 6. Pero tal vez sea un mejor flujo de trabajo para escribir el código normalmente y no fusionarlo hasta que pasemos a Xcode 6 .. Gracias.
VinceFior
@VinceFior el enfoque recomendado es compilar condicionalmente usando la macro definida por el SDK __IPHONE_OS_VERSION_MAX_ALLOWED( #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
Steven Kramer
50
- (void)startLocationManager
{
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
    [locationManager requestWhenInUseAuthorization]; // Add This Line


}

Y a su archivo info.plist ingrese la descripción de la imagen aquí

neo D1
fuente
1
Encontramos una solución similar de manera más descriptiva en datacalculation.blogspot.in/2014/11/…
Prueba de iOS el
2
@Hemang: Según la documentación de Apple Dev: es seguro iniciar los servicios de ubicación antes de determinar el estado de autorización de su aplicación. Aunque puede iniciar los servicios de ubicación, esos servicios no entregan ningún dato hasta que el estado de la autorización cambie a kCLAuthorizationStatusAuthorizedAlways o kCLAuthorizationStatusAuthorizedWhenInUse.
Andrew
Un poco tarde, pero le recomiendo que oculte partes irrelevantes de su archivo plist, especialmente FacebookAppID
Przemysław Wrzesiński
Gracias Pero eso es solo una muestra ficticia :)
neo D1
También es importante que el proyecto apunte a la lista de información correcta (aquella en la que se define la clave). Eso se determina en la configuración de compilación del proyecto en Archivo Info.plist.
clearlight
30

Según los documentos de Apple:

A partir de iOS 8, la presencia de un NSLocationWhenInUseUsageDescriptiono una NSLocationAlwaysUsageDescriptionse requiere valor clave en el archivo Info.plist de su aplicación. También es necesario solicitar permiso al usuario antes de registrarse para recibir actualizaciones de ubicación, ya sea llamando [self.myLocationManager requestWhenInUseAuthorization]o [self.myLocationManager requestAlwaysAuthorization]dependiendo de su necesidad. La cadena que ingresó en Info.plist se mostrará en el siguiente diálogo.

Si el usuario concede permiso, es lo de siempre. Si niegan el permiso, no se informa al delegado de las actualizaciones de ubicación.

metateorético
fuente
Encontré una descripción simple aquí en datacalculation.blogspot.in/2014/11/…
Prueba de iOS el
28
- (void)viewDidLoad
{

    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
        NSUInteger code = [CLLocationManager authorizationStatus];
        if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
            // choose one request according to your business.
            if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
                [self.locationManager requestAlwaysAuthorization];
            } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
                [self.locationManager  requestWhenInUseAuthorization];
            } else {
                NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
            }
        }
    }
    [self.locationManager startUpdatingLocation];
}

>  #pragma mark - CLLocationManagerDelegate

    - (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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        NSLog(@"didUpdateToLocation: %@", newLocation);
        CLLocation *currentLocation = newLocation;

        if (currentLocation != nil) {
            longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
            latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
        }
    }

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 solicitarle 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 falla al delegado (ya que nunca comenzó, no puede fallar). También fallará si agrega una o ambas claves pero se olvida de 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 teclas toman una cadena

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

ingrese la descripción de la imagen aquí

Adarsh ​​GJ
fuente
19

Mi solución que se puede compilar en Xcode 5:

#ifdef __IPHONE_8_0
    NSUInteger code = [CLLocationManager authorizationStatus];
    if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
        // choose one request according to your business.
        if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
            [self.locationManager requestAlwaysAuthorization];
        } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
            [self.locationManager  requestWhenInUseAuthorization];
        } else {
            NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
        }
    }
#endif
    [self.locationManager startUpdatingLocation];
Yinfeng
fuente
2
Buena solución dinámica, para usar en todas las aplicaciones. Sin embargo, cambiaría el orden y, en lugar de buscar el iPhone 8.0, verificaría si el administrador de ubicación responde a la autorización y luego ejecutaría el estado de autorización para obtener el código. Esto lo hará más universal.
zirinisp
Trabajó en xCode 7.2 también.
Totoro
17

El antiguo código para pedir ubicación no funcionará en iOS 8. Puede probar este método para la autorización de ubicación:

- (void)requestAlwaysAuthorization
{
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    // If the status is denied or only granted for when in use, display an alert
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status ==        kCLAuthorizationStatusDenied) {
        NSString *title;
        title = (status == kCLAuthorizationStatusDenied) ? @"Location services are off" :   @"Background location is not enabled";
        NSString *message = @"To use background location you must turn on 'Always' in the Location Services Settings";

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
                                                            message:message
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];
        [alertView show];
    }
    // The user has not enabled any location services. Request background authorization.
    else if (status == kCLAuthorizationStatusNotDetermined) {
        [self.locationManager requestAlwaysAuthorization];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        // Send the user to the Settings for this app
        NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:settingsURL];
    }
}
Nits007ak
fuente
UIAlertView ha quedado en desuso. En su lugar, debe usar UIAlertController.
Pasan Premaratne
Sí, sé que está en desuso, pero esto también funcionará. pero sí, mejor use UIAlertController para IOS8.
Nits007ak
12

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 pedirle que comience

info.plist:

<key>NSLocationUsageDescription</key>
<string>I need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need location</string>

Agregue esto a su código

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}
porJeevan
fuente
1
no está claro si su pseudocódigo es una llamada de preprocesador o una llamada normal
El Dude
1
Agregue esto a sus constantes.ho archivo .pch: #define IS_OS_8_OR_LATER ([[UIDevice currentDevice] .systemVersion floatValue]> = 8.0)
OxenBoxen
¿Por qué le solicitará tanto, se debe añadir un comentario mencionando sólo para usar uno u otro en función de sus necesidades de aplicación
powerj1984
la parte info.plist es bastante fácil de hacer en Unity3d, pero ¿cómo agregaría la parte del código si uso unity3d? dónde ?
CthulhuJon
11

Un error común para los desarrolladores de Swift:

Primero asegúrese de agregar un valor a la lista para cualquiera NSLocationWhenInUseUsageDescriptiono NSLocationAlwaysUsageDescription.

Si todavía no ve una ventana emergente pidiendo autorización, observe si está poniendo la líneavar locationManager = CLLocationManager() en el viewDidLoadmétodo de su controlador de vista . Si lo hace, incluso si llama locationManager.requestWhenInUseAuthorization(), no aparecerá nada. Esto se debe a que después de que viewDidLoad se ejecuta, la variable locationManager se desasigna (se borra).

La solución es ubicar la línea var locationManager = CLLocationManager()en la parte superior del método de clase.

st.derrick
fuente
9

Antes [locationManager startUpdatingLocation];, agregue una solicitud de servicios de ubicación de iOS8:

if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    [locationManager requestAlwaysAuthorization];

Edite la aplicación Info.plisty agregue la clave NSLocationAlwaysUsageDescriptioncon el valor de cadena que se mostrará al usuario (por ejemplo,We do our best to preserve your battery life. )

Si su aplicación necesita servicios de ubicación solo mientras la aplicación está abierta, reemplace:

requestAlwaysAuthorizationcon requestWhenInUseAuthorizationy

NSLocationAlwaysUsageDescriptioncon NSLocationWhenInUseUsageDescription.

budidino
fuente
9

Estaba trabajando en una aplicación que se actualizó a iOS 8 y los servicios de ubicación dejaron de funcionar. Probablemente obtendrá un error en el área de depuración de la siguiente manera:

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

Hice el procedimiento menos intrusivo. Primero agregue la NSLocationAlwaysUsageDescriptionentrada a su info.plist:

Ingrese la descripción de la imagen aquí

Tenga en cuenta que no completé el valor de esta clave. Esto todavía funciona, y no estoy preocupado porque esta es una aplicación interna. Además, ya hay un título que solicita el uso de servicios de ubicación, por lo que no quería hacer nada redundante.

A continuación, creé un condicional para iOS 8:

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

Después de esto, el locationManager:didChangeAuthorizationStatus:método es llamar:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:  (CLAuthorizationStatus)status
{
    [self gotoCurrenLocation];
}

Y ahora todo funciona bien. Como siempre, consulte la documentación .

Kris Utter
fuente
7

Solución con compatibilidad con versiones anteriores:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}

Configure la clave NSLocationWhenInUseUsageDescription en su Info.plist

hrchen
fuente
2
Esto no es correcto, ¿qué pasa con el caso kCLAuthorizationStatusDenied? salta a otra cosa y comienza a actualizar la ubicación que no es correcta.
electronix384128
@BenMarten No creo que deba importar. Deberías manejar eso tú mismo locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error. Sin embargo, olvidó agregar startUpdatingLocation a la instrucción if, por lo que después de que lo aceptan o lo niegan, en realidad no llama a startUpdateLocation.
Chris
6

Solución con compatibilidad con versiones anteriores que no produce advertencias de Xcode:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
  [self.locationManager respondsToSelector:requestSelector]) {
((void (*)(id, SEL))[self.locationManager methodForSelector:requestSelector])(self.locationManager, requestSelector);
  [self.locationManager startUpdatingLocation];
} else {
  [self.locationManager startUpdatingLocation];
}

NSLocationWhenInUseUsageDescriptionClave de configuración en su Info.plist.

Para iOS versión 11.0+ : NSLocationAlwaysAndWhenInUseUsageDescriptionclave de configuración en su Info.plist. junto con otras 2 llaves.

Alexander Belyavskiy
fuente
Esto no es correcto, ¿qué pasa con el caso kCLAuthorizationStatusDenied? salta a otra cosa y comienza a actualizar la ubicación que no es correcta.
electronix384128
Esto es bastante extraño, esto funciona bien para mí, no muy bien, tanto con permitir como sin permitir. Incluso la solución de Jacob parece precisa pero no funcionó para mí. Extraño pero trabajado !!!
josh
Llamar a [self.locationManager startUpdatingLocation] justo después de requestWhenInUseAuthorization no tiene sentido
Kostia Kim
5

Esto es un problema con iOS 8 Agregue esto a su código

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

y para info.plist:

 <key>NSLocationUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationAlwaysUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationWhenInUseUsageDescription</key>
 <string>I need location</string>
Pooja Patel
fuente
NSLocationUsageDescriptionno se usa en iOS8 +
Carlos Ricardo
4

Para acceder a la ubicación del usuario en iOS 8, deberá agregar,

NSLocationAlwaysUsageDescription in the Info.plist 

Esto le pedirá al usuario permiso para obtener su ubicación actual.

Annu
fuente
4

Procedimiento Objective-C Siga las siguientes instrucciones:

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

Necesita agregar dos claves en plist y proporcionar el mensaje como se muestra a continuación:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

ingrese la descripción de la imagen aquí Para iOS-10 y a continuación:

NSLocationWhenInUseUsageDescription

ingrese la descripción de la imagen aquí

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

Métodos delegados

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

Procedimiento rápido

Siga las siguientes instrucciones:

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

Necesita agregar dos claves en plist y proporcionar el mensaje como se muestra a continuación:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

ingrese la descripción de la imagen aquí Para iOS-10 y a continuación:

ingrese la descripción de la imagen aquí

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

Métodos delegados

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

}
Alok
fuente
Asegúrese de que NSLocationAlwaysUsageDescription también se agregue; de ​​lo contrario, recibirá un error al cargar en la tienda de aplicaciones.
Alok
Su mensaje también debe ser informativo; de lo contrario, Apple rechazará la aplicación durante el proceso de revisión.
Alok
3

Para aquellos que utilizan Xamarin , he tenido que añadir la clave NSLocationWhenInUseUsageDescriptiona la info.plist manualmente ya que no estaba disponible en los menús desplegables, ya sea en Xamarin 5.5.3 Build 6 o XCode 6.1 - solamente NSLocationUsageDescriptionestaba en la lista, y que causó el CLLocationManagerque siga fallar en silencio

Derreck Dean
fuente
2
        // ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string

        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];
        }
        [self.locationManager startUpdatingLocation];


    // Location Manager Delegate Methods    
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
        NSLog(@"%@", [locations lastObject]);

}
Prosenjit Goswami
fuente
2

Un pequeño ayudante para todos ustedes que tienen más de un archivo Info.plist ...

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Add NSLocationWhenInUseUsageDescription string' {} 

Agregará la etiqueta necesaria a todos los archivos Info.plist en el directorio actual (y subcarpetas).

Otro es:

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Set NSLocationWhenInUseUsageDescription $YOURDESCRIPTION' {} 

Agregará su descripción a todos los archivos.

Peter Mortensen
fuente
2

Recibo un error similar en iOS9 (trabajando con Xcode 7 y Swift 2): Intento de iniciar las actualizaciones de ubicación de MapKit sin solicitar autorización de ubicación. Debe llamar - [CLLocationManager requestWhenInUseAuthorization] o - [CLLocationManager requestAlwaysAuthorization] primero. Estaba siguiendo un tutorial pero el tutor estaba usando iOS8 y Swift 1.2. Hay algunos cambios en Xcode 7 y Swift 2, encontré este código y funciona bien para mí (si alguien necesita ayuda):

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    // MARK: Properties
    @IBOutlet weak var mapView: MKMapView!

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        self.mapView.showsUserLocation = true

    }

    // MARK: - Location Delegate Methods

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let location = locations.last
        let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
        self.mapView.setRegion(region, animated: true)
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("Errors: " + error.localizedDescription)
    }
}

Finalmente, lo puse en info.plist: Lista de propiedades de información: NSLocationWhenInUseUsageDescription Valor: la aplicación necesita servidores de ubicación para el personal

Jorge Luis Jiménez
fuente
2

Para acceder a la ubicación de los usuarios en iOS. Necesitas agregar dos llaves

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

en el archivo Info.plist.

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Because I want to know where you are!</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Want to know where you are!</string>

Ver esta imagen a continuación.

Imagen Info.plist

Vinoth Vino
fuente
1
  1. Agregue la clave NSLocationWhenInUseUsageDescriptiono NSLocationAlwaysUsageDescription(uso de GPS de fondo) con una cadena que solicite el uso de GPS en info.plistcada objetivo.

  2. Solicite permiso ejecutando:

    [self initLocationManager: locationManager];

Donde initLocationManageres:

// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{

    locationManager = [[CLLocationManager alloc]init];

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

Recuerde que si las teclas no están en cada uno info.plistpara cada objetivo, la aplicación no le preguntará al usuario. El ifproporciona compatibilidad con iOS 7 y el respondsToSelector:método garantiza la compatibilidad futura en lugar de resolver el problema para iOS 7 y 8.

juan Isaza
fuente
0

El problema para mí fue que la clase que era CLLocationManagerDelegateera privada, lo que impedía que se llamara a todos los métodos delegados. Supongo que no es una situación muy común, pero pensé que lo mencionaría en caso de que ayude a alguien.

Lorenzo
fuente
0

Añado clave en los que InfoPlist.stringsen iOS 8.4, mini iPad 2. Funciona también. No configuro ninguna clave, como NSLocationWhenInUseUsageDescription, en mi Info.plist.


InfoPlist.strings :

"NSLocationWhenInUseUsageDescription" = "I need GPS information....";

La base de este hilo , decía as in iOS 7, se puede localizar en InfoPlist.strings. En mi prueba, esas claves se pueden configurar directamente en el archivo InfoPlist.strings.

Entonces, lo primero que debe hacer es agregar una o ambas> claves siguientes 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 ubicación para saber dónde se encuentra" que, como en iOS 7 , se puede localizar en el archivo InfoPlist.strings.


ACTUALIZAR:

Creo que @IOSel método es mejor. Agregue clave a Info.plistcon valor vacío y agregue cadenas localizadas a InfoPlist.strings.

AechoLiu
fuente