El diálogo de permiso de ubicación actual desaparece demasiado rápido

175

Mi aplicación toma la ubicación del usuario, obtiene las coordenadas y proporciona una distancia hacia o desde su destino u origen. Todos estos destinos posibles se muestran en una vista de tabla, por lo que obtengo las coordenadas de los usuarios al mismo tiempo que llenan la tabla. ¡Lo único es que la vista de alerta que solicita la ubicación de los usuarios aparece y desaparece tan rápido que es imposible hacer clic en ella!

¿Hay alguna forma de presentar manualmente esta alerta cuando la aplicación se carga por primera vez? Traté de obtener la ubicación del usuario cuando la aplicación se carga para tratar de forzar que se muestre la alerta, pero eso no funcionó.

Glenn Sayers
fuente

Respuestas:

698

Si bien es difícil de rastrear, la solución para esto es bastante simple.

A través de muchas pruebas y errores, descubrí que si bien el cuadro de diálogo de acceso a la ubicación aparece cuando intenta acceder a cualquier servicio de ubicación en la aplicación por primera vez, el cuadro de diálogo desaparece por sí solo (sin ninguna interacción del usuario) si el CLLocationManagerobjeto se libera antes El usuario responde al diálogo.

Estaba creando una CLLocationManagerinstancia en mi viewDidLoadmétodo. Como se trataba de una instancia local para el método, ARC lanzó la instancia después de que el método completara la ejecución. Tan pronto como se lanzó la instancia, el diálogo desapareció. La solución fue bastante simple. Cambie la CLLocationManagerinstancia de ser una variable de nivel de método para ser una variable de instancia de nivel de clase. Ahora la CLLocationManagerinstancia solo se libera una vez que se descarga la clase.

Zoli
fuente
117
Ojalá pudiera darte +100
codificador
1
Simplemente golpee el mismo problema con Xamarin.iOS. Haga que el alcance de la clase CLLocationManager y el diálogo permanezca visible.
Krumelur
1
Yaaaaa ... si pudieras seguir adelante y darte un aumento, eso sería muy bueno. (En serio, este es un gran ahorro para mí también)
Garfonzo
2
Tengo que unirme a esta fiesta también. Aquí, ¡consigue un Internet High Five de mi parte!
Matthieu Riegler
3
Cualquiera que tenga este problema en Swift, asegúrese de mover la declaración de LocationManager fuera de viewDidLoad. ¡Salud!
KD.
5

Mismo síntoma, causa diferente: no llame startUpdatingLocationmás de una vez seguidas .

Accidentalmente había estructurado cosas de tal manera que el código estaba llamando involuntariamente startUpdatingLocationdos veces seguidas, lo que aparentemente es malo. También podría haber tenido algo que ver con la elección de la cola, ya que estaba esperando comenzar a actualizar en espera del resultado de una solicitud de red, pero no necesitaba hacer ninguna magia GCD para solucionarlo ... solo necesitaba asegurarme de que No repitió el comienzo.

Espero que alguien pueda beneficiarse de mi dolor. :)

clozach
fuente
5

Me he enfrentado a una situación similar. Después de depurar encontré

let locationManager = CLLocationManager()

se llama en un alcance de método, pero debe llamarse globalmente.

¿Por qué?

En pocas palabras, locationManager se ha lanzado después de que el método haya regresado. Pero no debe publicarse hasta que el usuario otorgue o deniegue el permiso

Ankur Lahiry
fuente
4

Caigo en el mismo problema (al menos por síntomas). En mi caso, el problema estaba en el - (void)applicationWillResignActive:(UIApplication *)application;método, donde estaba lanzando mi CLLocationManagerinstancia como parte de la preparación para la transición de fondo. Cuando lo quité y lo dejé solo en - (void)applicationDidEnterBackground:(UIApplication *)application;el problema desapareció.
La parte complicada es que la alerta de ubicación central SI suspende su aplicación mientras está en primer plano.
Espero que te ayude, me llevó mucho tiempo encontrar a ese bastardo :)

Ariel
fuente
4

Sé que esta es una respuesta muy tardía. Pero puede ayudar a alguien. También enfrenté el mismo problema y pasé una hora para identificar el problema. Al principio mi código era así.

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

CLLocation *location = locationManager.location;
//my stuff with the location

    [locationManager release];

Ahora la alerta de ubicación desapareció rápidamente. Cuando descomento la última línea, funciona correctamente.

   // [locationManager release];
Ramaraj T
fuente
3
Esto es verdad. La única advertencia que agregaría a esta respuesta es que cuando su proyecto tiene ARC habilitado, no necesita incluir la declaración de lanzamiento en su código y aún se encontrará con este problema. La única forma de resolver el problema en ese escenario es hacer que la variable sea de nivel de clase en lugar de nivel de método.
Zoli
3

También me encontré con este problema, pero la solución en mi caso resultó ser completamente diferente a la respuesta aceptada.

En mi aplicación, estaba llamando stopUpdatingLocationdesde applicationWillResignActive. Esto fue un problema porque applicationWillResignActivese llama cuando aparece el diálogo de permiso. Esto estaba causando stopUpdatingLocationinmediatamente después startUpdatingLocation, por lo que el diálogo desaparecería inmediatamente.

La solución era simplemente llamar stopUpdatingLocationdesde su applicationDidEnterBackgroundlugar.

Alan Kinnaman
fuente
2

Esto me estaba sucediendo mientras usaba el simulador de iOS. Determiné que estaba ocurriendo porque mi Esquema de ejecución simulaba una ubicación. Creo que esto tiene el mismo efecto que llamar locationManager.startUpdatingLocation()en el lanzamiento y, por lo tanto, estaba cerrando el diálogo.

Desmarcar la casilla de verificación "Permitir simulación de ubicación" en el cuadro de diálogo Editar esquemas solucionó el problema. Una vez que funcione como lo desee y se establezca el permiso, puede volver a habilitar la simulación de ubicación y el simulador funcionará bien a partir de ese momento.

Paolo
fuente
Esto funcionó en cierta medida para mí. Al menos pude ver el diálogo
CppChase
2

Swift 4 y iOS 11 :

Asegúrese de haber agregado líneas de privacidad (tanto siempre como whenInUse ) a su .plistarchivo y agregue CoreLocationFramework a su proyecto

El diálogo de permiso de ubicación aparece correctamente cuando he cambiado:

locationManager.requestAlwaysAuthorization()

con:

locationManager.requestWhenInUseAuthorization()

PD : He intentado TODOS los consejos y todo falla (solicitar autorización para viewDidLoad, en varlugar de letpara locationManager, no comenzar startUpdatingLocation()después de la solicitud ... Creo que es un error y espero que lo resuelvan lo antes posible ...

Alessandro Ornano
fuente
También he seguido todos los consejos, pero siempre tengo el mismo problema. El diálogo de permiso de ubicación aparece brevemente, luego desaparece inmediatamente. Luego aparece mi permiso de diálogo de notificación (este es normal), cuando presiono aceptar o rechazar, aparece otro permiso de ubicación (esta vez se queda y me permite aceptar o rechazar).
@BitoQ Sí, para mí también. La misma situación pero al menos podemos ver este diálogo, espero que con el próximo iOS 11.1 corrijan este error ...
Alessandro Ornano
1

La solución SWIFT 4 @Zoli se verá así:

class WhateverViewController: UIViewController {
    let locationManager = CLLocationManager() // here is the point of the @Zoli answer

    // some code
    override func viewDidLoad() {
        super.viewDidLoad()

        // some other code
        locationManager.requestWhenInUseAuthorization()
        // some other code
    }
}
wm.p1us
fuente
0

usted define más la variable locationManager como objeto global.

@interface ViewController : UIViewController
{
    CLLocationManager *locationManager;
}
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    CLLocationManager *locationManager = [[CLLocationManager alloc] init];
    [locationManager startUpdatingLocation];
}
Mahdi Nili
fuente
0

Me encontré con la misma situación tuya.

  • Mi solución cambió de variable local a instancia de miembro.
  • La causa fue que la instancia local? No era válida después de que se terminó el método, que incluye la variable local (de extender mi locationManager)
  • Mi env .: Xcode9.3.1
#importar 
@interface ViewController ()

@final

@implementation ViewController
@synthesize locManager; // después
- (nulo) viewDidLoad {
    [super viewDidLoad];
    // Realice cualquier configuración adicional después de cargar la vista, generalmente desde una punta.

    // MyLocationService * locManager = [[BSNLocationService alloc] init: nil]; // antes de. la loc. delegado no funcionó porque la instancia se volvió inválida después de este método.
    self-> locManager = [[MyLocationService alloc] init: nil]; // después
    locManager.startService;
}

usuario2058374
fuente