La boîte de dialogue d'autorisation de localisation actuelle disparaît trop rapidement

175

Mon application prend la position de l'utilisateur, obtient les coordonnées et fournit une distance depuis ou vers sa destination ou son origine. Toutes ces destinations possibles sont affichées dans une vue de tableau, donc j'obtiens les coordonnées des utilisateurs en même temps que le remplissage du tableau. La seule chose est que la vue d'alerte qui demande l'emplacement des utilisateurs apparaît puis disparaît si rapidement qu'il est impossible de cliquer dessus!

Existe-t-il un moyen de présenter manuellement cette alerte lors du premier chargement de l'application? J'ai essayé d'obtenir l'emplacement de l'utilisateur lorsque l'application se charge pour essayer de forcer l'alerte à s'afficher, mais cela n'a pas fonctionné.

Glenn Sayers
la source

Réponses:

700

Bien que difficile à trouver, la solution est assez simple.

Grâce à de nombreux essais et erreurs, j'ai découvert que, tandis que la boîte de dialogue d'accès à l'emplacement apparaît lorsque vous essayez d'accéder à des services de localisation dans l'application pour la première fois, la boîte de dialogue disparaît d'elle-même (sans aucune interaction de l'utilisateur) si l' CLLocationManagerobjet est libéré avant l'utilisateur répond au dialogue.

Je créais une CLLocationManagerinstance dans ma viewDidLoadméthode. Comme il s'agissait d'une instance locale de la méthode, l'instance a été libérée par ARC après la fin de l'exécution de la méthode. Dès que l'instance a été libérée, la boîte de dialogue a disparu. La solution était plutôt simple. Remplacez l' CLLocationManagerinstance d'une variable de niveau méthode par une variable d'instance de niveau classe. Désormais, l' CLLocationManagerinstance n'est libérée qu'une fois la classe déchargée.

Zoli
la source
117
J'aimerais pouvoir vous donner +100
codeur
1
Frappez simplement le même problème avec Xamarin.iOS. Définissez la portée de la classe CLLocationManager et la boîte de dialogue reste visible.
Krumelur
1
Yaaaaa ... si vous pouviez aller de l'avant et vous donner une augmentation, ce serait greeeeeaaaat. (Sérieusement, c'est un gros arrêt pour moi aussi)
Garfonzo
2
Je dois aussi rejoindre ce parti. Tenez, obtenez un Internet High Five de ma part!
Matthieu Riegler
3
Quiconque rencontre ce problème dans Swift veille à déplacer la déclaration de LocationManager hors de viewDidLoad. À votre santé!
KD.
5

Même symptôme, cause différente: ne pas appeler startUpdatingLocationplus d'une fois de suite .

J'ai eu accidentellement des choses structurées de telle sorte que le code appelait involontairement startUpdatingLocationdeux fois de suite, ce qui est apparemment mauvais. Cela pouvait aussi avoir quelque chose à voir avec le choix de la file d'attente puisque j'attendais de commencer la mise à jour en attendant le résultat d'une demande réseau, mais je n'avais pas besoin de faire de magie GCD pour le réparer ... juste besoin de m'assurer que je n'a pas répété le début.

J'espère que quelqu'un pourra profiter de ma douleur. :)

Clozach
la source
5

J'ai fait face à la situation similaire. Après le débogage, j'ai trouvé

let locationManager = CLLocationManager()

est appelée dans une portée de méthode, mais elle doit être appelée globalement.

Pourquoi?

En un mot, locationManager a été publié après le retour de la méthode. Mais il ne devrait pas être publié tant que l'utilisateur n'a pas donné ou refusé l'autorisation

Ankur Lahiry
la source
4

Je tombe dans le même problème (au moins par les symptômes). Dans mon cas, le problème était dans la - (void)applicationWillResignActive:(UIApplication *)application;méthode, où je publiais mon CLLocationManagerinstance dans le cadre de la préparation de la transition en arrière-plan. Quand je l'ai enlevé et laissé seulement dans - (void)applicationDidEnterBackground:(UIApplication *)application;le problème est parti.
La partie délicate est que l'alerte Core Location suspend votre application alors qu'elle est encore au premier plan.
J'espère que cela vous aidera, il m'a fallu beaucoup de temps pour fonder ce salaud :)

Ariel
la source
4

Je sais que c'est une réponse très tardive. Mais cela peut aider quelqu'un. J'ai également fait face au même problème et j'ai passé une heure à identifier le problème. Au début, mon code était comme ça.

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

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

    [locationManager release];

Maintenant, l'alerte de localisation a disparu rapidement. Lorsque je décommente la dernière ligne, cela fonctionne correctement.

   // [locationManager release];
Ramaraj T
la source
3
C'est vrai. La seule mise en garde que j'ajouterais à cette réponse est que lorsque votre projet a activé ARC, vous n'avez pas besoin d'inclure la déclaration de version dans votre code et vous rencontrerez toujours ce problème. La seule façon de résoudre le problème dans ce scénario consiste à créer la variable au niveau de la classe au lieu du niveau de la méthode.
Zoli
3

J'ai également rencontré ce problème, mais la solution dans mon cas s'est avérée complètement différente de la réponse acceptée.

Dans mon application, j'appelais stopUpdatingLocationdepuis applicationWillResignActive. C'était un problème car il applicationWillResignActiveest appelé lorsque la boîte de dialogue d'autorisation apparaît. Cela provoquait stopUpdatingLocationimmédiatement après startUpdatingLocation, c'est pourquoi le dialogue disparaîtrait immédiatement.

La solution était simplement d'appeler stopUpdatingLocationà la applicationDidEnterBackgroundplace.

Alan Kinnaman
la source
2

Cela m'est arrivé lors de l'utilisation du simulateur iOS. J'ai déterminé que cela se produisait parce que mon programme d'exécution simulait un emplacement. Je pense que cela a le même effet que l'appel locationManager.startUpdatingLocation()au lancement et donc cela fermait la boîte de dialogue.

Le fait de décocher la case "Autoriser la simulation d'emplacement" dans la boîte de dialogue Modifier les schémas a résolu le problème. Une fois que cela fonctionne comme vous le souhaitez et que l'autorisation est définie, vous pouvez réactiver la simulation de localisation et le simulateur fonctionnera correctement à partir de là.

Paolo
la source
Cela a fonctionné dans une certaine mesure pour moi. Au moins j'ai pu voir le dialogue
CppChase
2

Swift 4 et iOS 11 :

Assurez-vous d'avoir ajouté des lignes de confidentialité (à la fois toujours et lors de l' utilisation ) à votre .plistfichier et ajoutez CoreLocationFramework à votre projet

La boîte de dialogue d'autorisation de localisation s'affiche correctement lorsque j'ai changé:

locationManager.requestAlwaysAuthorization()

avec:

locationManager.requestWhenInUseAuthorization()

PS .: J'ai essayé TOUS les conseils et tout échoue (demander l'autorisation à viewDidLoad, varau lieu de letpour locationManager, ne pas démarrer startUpdatingLocation()après la demande ... Je pense que c'est un bogue et j'espère qu'ils le résoudront le plus rapidement possible.

Alessandro Ornano
la source
J'ai suivi tous les conseils aussi, mais j'ai toujours le même problème. La boîte de dialogue d'autorisation de localisation apparaît brièvement, puis disparaît immédiatement. Ensuite, ma permission de dialogue de notification apparaît (celle-ci est normale), lorsque j'appuie sur accepter ou refuser, une autre autorisation de localisation apparaît (cette fois, elle reste et me laisse accepter ou refuser).
@BitoQ Oui, pour moi aussi. Même situation mais au moins nous pouvons voir cette boîte de dialogue, j'espère qu'avec le prochain iOS 11.1 ils corrigeront ce bogue ..
Alessandro Ornano
1

La solution SWIFT 4 @Zoli ressemblera à ceci:

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
la source
0

vous définissez le plus la variable locationManager comme objet global.

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

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

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

J'ai rencontré la même situation que la vôtre.

  • Ma solution est passée de variable locale à instance membre.
  • La cause était que l'instance locale? Était invalide après la fin de la méthode qui inclut la variable locale (d'étendre mon locationManager)
  • Mon environnement: Xcode9.3.1
#importer 
@interface ViewController ()

@fin

@implementation ViewController
@synthesize locManager; // après
- (void) viewDidLoad {
    [super viewDidLoad];
    // Effectuez toute configuration supplémentaire après le chargement de la vue, généralement à partir d'une pointe.

    // MyLocationService * locManager = [[BSNLocationService alloc] init: nil]; // avant. le loc. Le délégué n'a pas fonctionné car l'instance est devenue invalide après cette méthode.
    self-> locManager = [[MyLocationService alloc] init: nil]; // après
    locManager.startService;
}

user2058374
la source