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

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, чтобы это исправить ... просто нужно было убедиться, что я не повторить старт.

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

clozach
источник
5

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

let locationManager = CLLocationManager()

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

Зачем?

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

Анкур Лахири
источник
4

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

Ariel
источник
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()при запуске, поэтому диалог закрывался.

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

Paolo
источник
Это сработало для меня. По крайней мере, я должен был видеть диалог
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
    }
}
wm.p1us
источник
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;
}

user2058374
источник