Поточне діалогове вікно дозволу зникає занадто швидко


175

Мій додаток займає місцезнаходження користувача, отримує координати та надає відстань до місця призначення або його походження. Усі ці можливі пункти призначення відображаються у вигляді таблиці, тому я отримую координати користувачів одночасно із заповненням таблиці. Єдине, що відображається попереджувальний вигляд, який запитує місце розташування користувачів, зникає так швидко, що його неможливо натиснути!

Чи є спосіб вручну подати це сповіщення під час завантаження програми? Я спробував знайти місцезнаходження користувача, коли додаток завантажується, щоб спробувати примусити показ попередження, але це не вийшло.

Відповіді:


698

Хоча важко знайти, рішення для цього досить просте.

Через багато спроб та помилок я з'ясував, що в той час, коли з'являється діалогове вікно доступу до локації, коли ви намагаєтесь отримати доступ до будь-яких служб локації в додатку вперше, діалогове вікно зникає самостійно (без будь-якої взаємодії з користувачем), якщо CLLocationManagerоб'єкт звільнений раніше користувач відповідає на діалогове вікно.

Я створював CLLocationManagerекземпляр у своєму viewDidLoadметоді. Оскільки це був локальний екземпляр методу, екземпляр був випущений ARC після завершення методу виконання. Як тільки екземпляр був випущений, діалогове вікно зникло. Рішення було досить простим. Змініть CLLocationManagerекземпляр із змінної рівня методу на змінну екземпляра рівня класу. Тепер CLLocationManagerекземпляр випускається лише після завантаження класу.


117
Я б хотів, щоб я міг вам дати +100
кодер

1
Просто натисніть на ту ж проблему з Xamarin.iOS. Зробіть область CLLocationManager класом і діалогове вікно залишається видимим.
Крумельюр

1
Яаааа .... якби ви могли піти вперед і підняти собі підвищення, це було б greeeeeaaaat. (Серйозно, це теж велика економія для мене)
Гарфонцо,

2
Я повинен також приєднатися до цієї партії. Ось, отримайте від мене Інтернет-п'ять!
Матьє Ріглер

3
Усі, хто має цю проблему в Swift, переконайтеся, що ви перемістите декларацію LocationManager за межами viewDidLoad. Ура!
КД.

5

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

Я випадково структурував такі речі, що код ненавмисно дзвонив startUpdatingLocationдвічі поспіль, що, мабуть, погано. Це також може мати щось спільне з вибором черги, оскільки я чекав оновлення до очікування результату мережевого запиту, але мені не потрібно було робити жодної магії GCD, щоб виправити це ... просто потрібно, щоб переконатися, що я не повторив старт.

Сподіваюся, хтось зможе отримати користь від мого болю. :)


5

Я зіткнувся з подібною ситуацією. Після налагодження я знайшов

let locationManager = CLLocationManager()

називається в області застосування методу, але його слід називати глобально.

Чому?

У двох словах, після повернення методу locationManager було випущено. Але його не слід випускати, поки користувач не надасть або не відмовить у дозволі


4

Я потрапляю в те саме питання (принаймні за симптомами). У моєму випадку проблема полягала в - (void)applicationWillResignActive:(UIApplication *)application;методі, коли я випускав свій CLLocationManagerекземпляр у рамках підготовки до перехідного фону. Коли я її вийняв і залишив лише в - (void)applicationDidEnterBackground:(UIApplication *)application;проблемі, її немає.
Складна частина полягає в тому, що попередження Core Location DO призупиняє вашу програму, поки вона все ще на першому плані.
Сподіваюся, що це допоможе тобі, знадобилось мені багато часу, щоб знайти того сволота :)


4

Я знаю, що це дуже пізня відповідь. Але це може комусь допомогти. Я також зіткнувся з тією ж проблемою і витратив годину на виявлення проблеми. Спочатку мій код був таким.

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

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

    [locationManager release];

Тепер сповіщення про місцеположення швидко з’являлося. Коли я коментую останній рядок, він працює правильно.

   // [locationManager release];

3
Це правда. Єдине застереження, яке я хотів би додати до цієї відповіді, це те, що коли у вашому проекті увімкнено ARC, вам не потрібно включати у свій код заяву про випуск, і ви все ще зіткнетеся з цією проблемою. Єдиний спосіб вирішити проблему в цьому сценарії - це зробити змінний рівень класу замість рівня методу.
Золі

3

Я також зіткнувся з цією проблемою, але рішення в моєму випадку виявилося зовсім іншим, ніж прийнята відповідь.

У моєму додатку, я дзвоню stopUpdatingLocationз applicationWillResignActive. Ця проблема була через те applicationWillResignActive, що викликається, коли з’явиться діалогове вікно дозволу. Це було причиною stopUpdatingLocationодразу після цього startUpdatingLocation, через що діалог негайно зникне.

Рішенням було просто зателефонувати stopUpdatingLocationз applicationDidEnterBackgroundцього місця.


2

Це сталося зі мною під час використання iOS Simulator. Я визначив, що це відбувається, тому що моя схема запуску імітувала місцеположення. Я думаю, що це має такий же ефект, як дзвінки locationManager.startUpdatingLocation()при запуску, і тому воно закривало діалог.

Скасувавши прапорець "Дозволити моделювання місцеположення" у діалоговому вікні "Редагувати схеми" виправлено проблему. Після того, як він працює так, як вам потрібно, і встановлено дозвіл, ви можете знову ввімкнути імітацію локації, і з цього моменту тренажер буде працювати нормально.


Це працювало певною мірою для мене. По крайней мере, я повинен побачити діалог
CppChase

2

Swift 4 та iOS 11 :

Не забудьте додати до файлу рядки конфіденційності (як завжди, так і колиUUUse ) .plistта додати CoreLocationFramework до свого проекту

Діалогове вікно дозволу на місцезнаходження з’являється правильно, коли я змінив:

locationManager.requestAlwaysAuthorization()

з:

locationManager.requestWhenInUseAuthorization()

PS .: Я випробував ВСІ поради та всі помилки (авторизація запиту viewDidLoad, varзамість letLocationManager, не починається 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

Я зустрічався з вашою ситуацією.

  • Моє рішення було змінено з локальної змінної на інстанцію члена.
  • Причиною стало те, що локальний? Екземпляр був недійсним після закінчення методу, який включає локальну змінну (розширити мій locationManager)
  • My Env .: Xcode9.3.1
#import 
@interface ViewController ()

@end

@ реалізація ViewController
@synthesize locManager; // після
- (недійсний) viewDidLoad {
    [супер 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.