Okno dialogowe zezwolenia na bieżącą lokalizację znika zbyt szybko


175

Moja aplikacja pobiera lokalizację użytkownika, współrzędne i podaje odległość do lub od miejsca docelowego lub pochodzenia. Wszystkie te możliwe miejsca docelowe są pokazane w widoku tabeli, więc współrzędne użytkowników otrzymuję w tym samym czasie, gdy zapełniam tabelę. Jedyną rzeczą jest to, że widok alertu, który pyta o lokalizację użytkownika, pojawia się, a następnie znika tak szybko, że nie można go kliknąć!

Czy istnieje sposób, aby ręcznie przedstawić ten alert po pierwszym załadowaniu aplikacji? Próbowałem uzyskać lokalizację użytkownika, gdy aplikacja się ładuje, aby wymusić wyświetlenie alertu, ale to nie zadziałało.

Odpowiedzi:


698

Chociaż trudne do wyśledzenia, rozwiązanie tego jest dość proste.

Dzięki wielu próbom i błędom odkryłem, że podczas gdy okno dialogowe dostępu do lokalizacji pojawia się, gdy próbujesz uzyskać dostęp do jakichkolwiek usług lokalizacyjnych w aplikacji po raz pierwszy, okno dialogowe znika samoistnie (bez interakcji użytkownika), jeśli CLLocationManagerobiekt zostanie zwolniony wcześniej użytkownik odpowiada w oknie dialogowym.

Tworzyłem CLLocationManagerinstancję w mojej viewDidLoadmetodzie. Ponieważ była to lokalna instancja metody, instancja została zwolniona przez ARC po zakończeniu wykonywania metody. Po zwolnieniu instancji okno dialogowe zniknęło. Rozwiązanie było dość proste. Zmień CLLocationManagerinstancję ze zmiennej na poziomie metody na zmienną instancji na poziomie klasy. Teraz CLLocationManagerinstancja jest zwalniana dopiero po wyładowaniu klasy.


117
Chciałbym móc dać ci +100
koder

1
Po prostu napotkaj ten sam problem z Xamarin.iOS. Ustaw zakres klasy CLLocationManager, a okno dialogowe pozostanie widoczne.
Krumelur,

1
Yaaaaa… jeśli mógłbyś iść dalej i dać sobie podwyżkę, to byłoby greeeeeaaaat. (Poważnie, to też dla mnie duży zapis)
Garfonzo,

2
Ja też muszę dołączyć do tej imprezy. Proszę, przybij ode mnie internetową piątkę!
Matthieu Riegler

3
Każdy, kto ma ten problem w Swift, musi przenieść deklarację LocationManager poza viewDidLoad. Twoje zdrowie!
KD.

5

Ten sam symptom, inna przyczyna: nie dzwonić startUpdatingLocationwięcej niż raz z rzędu .

Przypadkowo ustrukturyzowałem rzeczy w taki sposób, że kod nieumyślnie dzwonił startUpdatingLocationdwa razy z rzędu, co najwyraźniej jest złe. Mogło to również mieć coś wspólnego z wyborem kolejki, ponieważ czekałem na rozpoczęcie aktualizacji w oczekiwaniu na wynik żądania sieciowego, ale nie musiałem robić żadnej magii GCD, aby to naprawić ... po prostu musiałem się upewnić, że nie powtórzył początku.

Mam nadzieję, że ktoś może skorzystać z mojego bólu. :)


5

Miałem do czynienia z podobną sytuacją. Po debugowaniu znalazłem

let locationManager = CLLocationManager()

jest wywoływana w zakresie metody, ale powinna być wywoływana globalnie.

Czemu?

W skrócie, locationManager został zwolniony po zwróceniu metody. Ale nie należy go udostępniać, dopóki użytkownik nie udzieli lub nie odmówi pozwolenia


4

Wpadam w ten sam problem (przynajmniej przez objawy). W moim przypadku problem tkwił w - (void)applicationWillResignActive:(UIApplication *)application;metodzie, w której zwalniałem CLLocationManagerinstancję w ramach przygotowań do przejścia w tle. Jak go usunąłem i zostawiłem tylko w - (void)applicationDidEnterBackground:(UIApplication *)application;problemie zniknął.
Problem polega na tym, że alert lokalizacji rdzenia NIE zawiesza aplikacji, gdy jest ona nadal na pierwszym planie.
Mam nadzieję, że ci to pomoże, dużo czasu zajęło mi znalezienie tego drania :)


4

Wiem, że to bardzo późna odpowiedź. Ale może komuś pomóc. Zmierzyłem się również z tym samym problemem i spędziłem godzinę, aby zidentyfikować problem. Na początku mój kod wyglądał tak.

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

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

    [locationManager release];

Teraz alert lokalizacji szybko zniknął. Kiedy odkomentuję ostatnią linię, działa poprawnie.

   // [locationManager release];

3
To prawda. Jedynym zastrzeżeniem, które chciałbym dodać do tej odpowiedzi, jest to, że gdy twój projekt ma włączony ARC, nie musisz umieszczać instrukcji wydania w swoim kodzie i nadal napotkasz ten problem. Jedynym sposobem rozwiązania problemu w tym scenariuszu jest ustawienie zmiennej na poziomie klasy zamiast metody na poziomie.
Zoli

3

Na ten problem też natknąłem się, ale rozwiązanie w moim przypadku okazało się zupełnie inne niż przyjęta odpowiedź.

W mojej aplikacji dzwoniłem stopUpdatingLocationz adresu applicationWillResignActive. Był to problem, ponieważ applicationWillResignActivejest wywoływany, gdy pojawia się okno dialogowe uprawnień. To powodowało stopUpdatingLocationzaraz potemstartUpdatingLocation , dlatego okno dialogowe natychmiast znikało.

Rozwiązaniem było po prostu do rozmowy stopUpdatingLocationz applicationDidEnterBackgroundzamiast.


2

Przydarzyło mi się to podczas korzystania z symulatora iOS. Ustaliłem, że dzieje się tak, ponieważ mój schemat uruchamiania symulował lokalizację. Myślę, że ma to taki sam efekt jak dzwonienielocationManager.startUpdatingLocation() podczas uruchamiania, więc zamykało okno dialogowe.

Usunięcie zaznaczenia pola wyboru „Zezwalaj na symulację lokalizacji” w oknie dialogowym Edytuj schematy rozwiązało problem. Gdy będzie działać tak, jak chcesz, a uprawnienia zostaną ustawione, możesz ponownie włączyć symulację lokalizacji, a symulator będzie od tego momentu działał dobrze.


To zadziałało dla mnie do pewnego stopnia. Przynajmniej widziałem dialog
CppChase

2

Swift 4 i iOS 11 :

Upewnij się, że do pliku dodano linie prywatności (zarówno zawsze, jak i kiedyInUse ) .plisti dodaj CoreLocationFramework do projektu

Okno dialogowe pozwolenia na lokalizację pojawia się poprawnie po zmianie:

locationManager.requestAlwaysAuthorization()

z:

locationManager.requestWhenInUseAuthorization()

PS :. Próbowałem WSZELKIE rad i wszystko zawiedzie (upoważnienie do żądania viewDidLoad, varzamiast letna locationManager, nie zaczynaj startUpdatingLocation()po request..I że to błąd i mam nadzieję, że go rozwiązać jak najszybciej ..


Ja też postępowałem zgodnie ze wszystkimi radami, ale zawsze mam ten sam problem. Okno dialogowe zezwolenia na lokalizację pojawia się na chwilę, a następnie natychmiast znika. Następnie pojawia się moje okno dialogowe powiadomienia (to jest normalne), kiedy naciskam przycisk akceptacji lub odrzucania, pojawia się inne zezwolenie na lokalizację (tym razem pozostaje i pozwól mi zaakceptować lub odrzucić).

@BitoQ Tak, dla mnie też. Ta sama sytuacja, ale przynajmniej widzimy to okno dialogowe, mam nadzieję, że w następnym iOS 11.1 naprawią ten błąd ..
Alessandro Ornano

1

Rozwiązanie SWIFT 4 @Zoli będzie wyglądać następująco:

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

0

najczęściej definiujesz zmienną locationManager jako obiekt globalny.

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

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

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

0

Spotkałem się z tą samą twoją sytuacją.

  • Moje rozwiązanie zostało zmienione ze zmiennej lokalnej na instancję składową.
  • Przyczyną było to, że lokalna instancja? Była niepoprawna po zakończeniu metody, która zawiera lokalną zmienną (rozszerzenia mojego locationManager)
  • Moja koperta: Xcode9.3.1
#import 
@interface ViewController ()

@koniec

@implementation ViewController
@synthesize locManager; // po
- (void) viewDidLoad {
    [super viewDidLoad];
    // Wykonaj dodatkowe ustawienia po załadowaniu widoku, zazwyczaj z końcówki.

    // MyLocationService * locManager = [[BSNLocationService przydziel] init: nil]; // przed. loc. delegat nie zadziałał, ponieważ wystąpienie stało się nieprawidłowe po tej metodzie.
    self-> locManager = [[MyLocationService assign] init: nil]; // po
    locManager.startService;
}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.