web-dev-qa-db-fra.com

Le dialogue d'autorisation d'emplacement actuel disparaît trop rapidement

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

Est-il possible 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'affichage de l'alerte, mais cela n'a pas fonctionné.

161
glenn sayers

Bien que difficile à localiser, la solution à ce problème est assez simple.

Après de nombreux essais et erreurs, j'ai découvert que, même si la boîte de dialogue d'accès à l'emplacement apparaît lorsque vous essayez d'accéder à l'un des services de localisation de 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 CLLocationManager l'objet est libéré avant que l'utilisateur ne réponde à la boîte de dialogue.

Je créais une instance CLLocationManager dans ma méthode viewDidLoad. S'agissant d'une instance locale de la méthode, l'instance a été publiée par ARC une fois l'exécution de la méthode terminée. Dès que l'instance a été publiée, la boîte de dialogue a disparu. La solution était plutôt simple. Changez l'instance CLLocationManager d'une variable de niveau méthode en une variable d'instance de classe. Maintenant, l'instance CLLocationManager n'est publiée que lorsque la classe est déchargée.

644
Zoli

Même symptôme, cause différente: ne pas appeler startUpdatingLocation plusieurs fois de suite.

J'avais accidentellement structuré des choses telles que le code appelait involontairement startUpdatingLocation deux fois de suite, ce qui est apparemment mauvais. Cela avait peut-être aussi quelque chose à voir avec le choix de la file d'attente depuis que j'attendais de commencer la mise à jour en attendant le résultat d'une requête réseau, mais je n'avais pas besoin de faire de magie GCD pour y remédier ... je devais juste m'assurer que je n'a pas répété le début.

J'espère que quelqu'un pourra bénéficier de ma douleur. :)

5
clozach

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 d'emplacement a rapidement disparu. Lorsque je décommenter la dernière ligne, cela fonctionne correctement.

   // [locationManager release];
4
Ramaraj T

Je tombe dans le même problème (au moins par symptômes). Dans mon cas, le problème se trouvait dans la méthode - (void)applicationWillResignActive:(UIApplication *)application;, où je publiais mon instance CLLocationManager dans le cadre de la préparation de la transition en arrière-plan. Lorsque je l'ai retiré et que je l'ai laissé uniquement dans - (void)applicationDidEnterBackground:(UIApplication *)application;, le problème a disparu.
La difficulté réside dans le fait que l’alerte Core Location DOIT suspendre votre application alors qu’elle est toujours au premier plan.
J'espère que cela vous aidera, cela m'a pris beaucoup de temps pour fonder ce bâtard :)

4
Ariel

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

Dans mon application, j'appelais stopUpdatingLocation depuis applicationWillResignActive. C'était un problème parce que applicationWillResignActive est appelé lorsque la boîte de dialogue d'autorisation apparaît. Cela causait stopUpdatingLocation immédiatement après startUpdatingLocation, raison pour laquelle le dialogue disparaîtrait immédiatement.

La solution consistait simplement à appeler stopUpdatingLocation de applicationDidEnterBackground à la place.

3
Alan Kinnaman

Swift 4 et iOS 11:

Assurez-vous d’avoir ajouté des lignes de confidentialité (à la fois toujours et lorsque InUse ) à votre fichier .plist et ajoutez CoreLocation Framework à votre projet

La boîte de dialogue d'autorisation d'emplacement apparaît correctement lorsque j'ai changé:

locationManager.requestAlwaysAuthorization()

avec:

locationManager.requestWhenInUseAuthorization()

PS .: J'ai essayé TOUS conseils et tout échoue (demande l'autorisation à viewDidLoad, var au lieu de let pour locationManager, ne lancez pas startUpdatingLocation() après requête..Je pense que c'est un bogue et j'espère qu'ils le résoudront dès que possible ..

2

Cela m’arrivait lors de l’utilisation du simulateur iOS. J'ai déterminé que cela se produisait car mon schéma d'exécution simulait un emplacement. Je pense que cela a le même effet que d’appeler locationManager.startUpdatingLocation() au lancement et qu’il fermait donc la boîte de dialogue.

Décocher la case "Autoriser la simulation d'emplacement" dans la boîte de dialogue Éditer 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 d'emplacement. Le simulateur fonctionnera ensuite correctement.

2
Paolo

Swift 4 La solution @Zoli ressemblera à:

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
    }
}
1
wm.p1us

J'ai fait face à la même situation. Après le débogage j'ai trouvé

let locationManager = CLLocationManager()

est appelé dans une étendue de méthode, mais il devrait être appelé 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.

1
Ankur Lahiry

vous définissez le plus souvent 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];
}
0
Mahdi Nili

J'ai rencontré la même situation que la tienne.

  • Ma solution a été changée de variable locale en instance de membre.
  • La cause était que l'instance locale? Était invalide après la méthode, ce qui inclut la variable locale (de extend my locationManager)
  • Mon Env .: Xcode9.3.1
 
 # import 
 @ interface ViewController () 
 
 @ end 
 
 @ implémentation ViewController 
 @ synthétiser locManager; // après 
 - (void) viewDidLoad {
 [super viewDidLoad]; 
 // Effectuez toute configuration supplémentaire après le chargement de la vue, généralement à partir d'un pointeur. 
 // MyLocationService * locManager = [[BSNLocationService alloc] init: nil]; // avant. la loc. delegate 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; 
} 
 
0
user2058374

Cela se produit lorsque vous créez une variable locale de classe ou un wrapper dans une fonction/méthode. Créer une variable d'instance devant contenir la classe d'emplacement/wrapper

0
Wasim