Диалог разрешения текущего местоположения исчезает слишком быстро


175

Мое приложение берет местоположение пользователя, получает координаты и обеспечивает расстояние до или от пункта назначения или источника. Все эти возможные пункты назначения показаны в табличном представлении, поэтому я получаю координаты пользователей одновременно с заполнением таблицы. Единственное, что вид предупреждения, который запрашивает местоположение пользователя, появляется, а затем исчезает так быстро, что невозможно щелкнуть по нему!

Есть ли способ вручную представить это предупреждение при первой загрузке приложения? Я попытался определить местоположение пользователя при загрузке приложения, чтобы попытаться вызвать предупреждение, но это не сработало.

Ответы:


700

Хотя это трудно отследить, решение для этого довольно простое.

Путем множества проб и ошибок я обнаружил, что, хотя при первом доступе к любым службам определения местоположения в приложении появляется диалоговое окно доступа к местоположению, оно исчезает само по себе (без какого-либо взаимодействия с пользователем), если CLLocationManagerобъект был освобожден ранее. пользователь отвечает на диалог.

Я создавал CLLocationManagerэкземпляр в моем viewDidLoadметоде. Поскольку это был локальный экземпляр метода, этот экземпляр был освобожден ARC после завершения выполнения метода. Как только экземпляр был выпущен, диалог исчез. Решение было довольно простым. Измените CLLocationManagerэкземпляр с переменной уровня метода на переменную экземпляра уровня класса. Теперь CLLocationManagerэкземпляр освобождается только после выгрузки класса.


117
Я хотел бы дать вам +100
кодер

1
Просто попробуйте ту же проблему с Xamarin.iOS. Сделайте область видимости класса CLLocationManager, и диалог останется видимым.
Krumelur

1
Yaaaaa .... если бы вы могли пойти дальше и сделать себе рейз, это было бы greeeeeaaaat. (Серьезно, для меня это тоже большое спасение)
Гарфонзо

2
Я тоже должен присоединиться к этой вечеринке. Вот, возьми интернет High Five от меня!
Матье Риглер,

3
Если у вас возникла эта проблема в Swift, убедитесь, что вы переместили объявление LocationManager за пределы viewDidLoad. Ура!
КД.

5

Тот же симптом, другая причина: не звонить startUpdatingLocationболее одного раза подряд .

Я случайно структурировал вещи так, что код непреднамеренно вызывал startUpdatingLocation дважды подряд, что явно плохо. Это могло также иметь отношение к выбору очереди, так как я ждал начала обновления в ожидании результата сетевого запроса, но мне не нужно было использовать магию GCD, чтобы это исправить ... просто нужно было убедиться, что я не повторить старт.

Надеюсь, кто-то сможет извлечь выгоду из моей боли. :)


5

Я сталкивался с подобной ситуацией. После отладки я нашел

let locationManager = CLLocationManager()

вызывается в области видимости метода, но он должен вызываться глобально.

Зачем?

В двух словах, locationManager был выпущен после возврата метода. Но это не должно быть выпущено, пока пользователь не даст или не запретит разрешение


4

Я попадаю в ту же проблему (по крайней мере, по симптомам). В моем случае проблема была в - (void)applicationWillResignActive:(UIApplication *)application;методе, где я выпускал свой CLLocationManagerэкземпляр как часть подготовки к фоновому переходу. Когда я его снял и оставил только - (void)applicationDidEnterBackground:(UIApplication *)application;проблема исчезла.
Сложность в том, что оповещение о базовом местоположении действительно приостанавливает работу вашего приложения, пока оно находится на переднем плане.
Надеюсь, что это поможет вам, у меня ушло много времени, чтобы найти этого ублюдка :)


4

Я знаю, что это очень поздний ответ. Но это может кому-то помочь. Я также столкнулся с той же проблемой и потратил час, чтобы определить проблему. Сначала мой код был таким.

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

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

    [locationManager release];

Теперь оповещение о местонахождении исчезло быстро. Когда я раскомментирую последнюю строку, она работает правильно.

   // [locationManager release];

3
Это верно. Единственное предостережение, которое я хотел бы добавить к этому ответу, заключается в том, что, когда в вашем проекте включена поддержка ARC, вам не нужно включать в свой код оператор release, и вы все равно столкнетесь с этой проблемой. Единственный способ решить проблему в этом сценарии - сделать переменную уровня класса, а не уровня метода.
Золи

3

Я тоже столкнулся с этой проблемой, но решение в моем случае оказалось совершенно другим, чем принятый ответ.

В моем приложении я звонил stopUpdatingLocationс applicationWillResignActive. Это было проблемой, потому что applicationWillResignActiveвызывается, когда появляется диалоговое окно разрешения. Это было причиной stopUpdatingLocationсразу после startUpdatingLocation, поэтому диалог сразу исчезнет.

Решение было просто вызов stopUpdatingLocationиз applicationDidEnterBackgroundвместо.


2

Это происходило со мной во время использования симулятора iOS. Я определил, что это происходит, потому что моя Схема пробега моделировала местоположение. Я думаю, что это имеет тот же эффект, что и вызов locationManager.startUpdatingLocation()при запуске, поэтому диалог закрывался.

Снятие флажка «Разрешить моделирование местоположения» в диалоговом окне «Редактирование схем» решило проблему. Как только он будет работать так, как вы хотите, и разрешение будет установлено, вы можете снова включить симуляцию местоположения, и с этого момента симулятор будет работать нормально.


Это сработало для меня. По крайней мере, я должен был видеть диалог
CppChase

2

Swift 4 и iOS 11 :

Обязательно добавьте строки конфиденциальности (как всегда, так и whenInUse ) в ваш .plistфайл и добавьте CoreLocationFramework в свой проект

Диалог разрешения местоположения отображается правильно, когда я изменился:

locationManager.requestAlwaysAuthorization()

с участием:

locationManager.requestWhenInUseAuthorization()

PS : Я перепробовал ВСЕ советы, и все не удалось (запросить авторизацию viewDidLoad, varа не letдля locationManager, не запускать startUpdatingLocation()после запроса ... Я думаю, что это ошибка, и я надеюсь, что они исправят ее как можно скорее ..


Я тоже следовал всем советам, но у меня всегда одна и та же проблема. На короткое время появляется диалоговое окно разрешения местоположения, а затем сразу исчезает. Затем появляется мое диалоговое разрешение для уведомлений (это нормально), когда я нажимаю принять или отклонить, появляется другое разрешение для местоположения (на этот раз оно остается и позволяет мне принять или отклонить).

@BitoQ Да, для меня тоже. Та же ситуация, но по крайней мере мы можем видеть это диалоговое окно, я надеюсь, что со следующей iOS 11.1 они исправят эту ошибку ..
Алессандро Орнано

1

Решение SWIFT 4 @Zoli будет выглядеть так:

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

Вы больше всего определяете переменную locationManager как глобальный объект.

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

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

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

0

Я встречал ту же ситуацию, что и ты.

  • Мое решение было изменено с локальной переменной на экземпляр члена.
  • Причиной было то, что локальный экземпляр был недействительным после завершения метода, который включает локальную переменную (из extension my locationManager)
  • Мой Env .: Xcode9.3.1
#Импортировать 
@interface ViewController ()

@конец

@implementation ViewController
@synthesize locManager; // после
- (void) viewDidLoad {
    [super viewDidLoad];
    // Выполнить любую дополнительную настройку после загрузки представления, обычно из кончика.

    // MyLocationService * locManager = [[BSNLocationService alloc] init: nil]; // перед. местонахождение делегат не работал, потому что экземпляр стал недействительным после этого метода.
    self-> locManager = [[MyLocationService alloc] init: nil]; // после
    locManager.startService;
}

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.