Служби локації, які не працюють в iOS 8


608

Мій додаток, який добре працював на iOS 7, не працює з iOS 8 SDK.

CLLocationManagerне повертає місцеположення, і я не бачу свого додатка в розділі Налаштування -> Служби локації . Я здійснив пошук у цьому питанні в Google, але нічого не вийшло. Що може бути не так?


Ви також можете використовувати це як довідковий додаток для рішення github.com/jbanford/ConstantLocationUpdates
ashok vadivelu

19
Про деякі зміни в менеджері місцеположень в iOS 8 я опублікував тут: nevan.net/2014/09/core-location-manager-changes-in-ios-8
nevan king

2
Ви можете спробувати використовувати цю бібліотеку , яка спрощує Core Location API , і виставляє інтерфейс на основі хороших блоків і нормує всі відмінності між різними версіями IOS (Повне розкриття: Я автор): github.com/lmirosevic/GBLocation
LmS

Я знайшов тут посилання datacalculation.blogspot.in/2014/11/…
Тест iOS

2
@nevanking Ви, сер! потрібна корона! Я боровся з цією проблемою з моменту змін і ще не знаходжу "посібника", як її виправити, це було недоброзичливо. Дякую вам за це посилання.
Патрік R

Відповіді:


1086

Я врешті-решт вирішив власну проблему.

Мабуть, в iOS 8 SDK потрібен дзвінок requestAlwaysAuthorization(для фонового розташування) або requestWhenInUseAuthorization(розташування лише тоді, коли передній план) CLLocationManagerперед запуском оновлень місцеположення.

Там також має бути NSLocationAlwaysUsageDescriptionабо NSLocationWhenInUseUsageDescriptionключ Info.plistз повідомленням , яке буде відображатися в рядку. Додавання цих вирішило мою проблему.

введіть тут опис зображення

Сподіваюся, це допоможе комусь іншому.

EDIT: Щоб отримати більш детальну інформацію, перегляньте: Core-Location-Manager-Changes-in-ios-8


6
Ви можете поділитися точним валером u, оновленим в Info.plist? Я не в змозі побачити цей ключ у моєму Info.plist. Я додав його і досі, здається, не працює. Я використовую Swift, iOS8 та XCode 6 beta 4
Vijay Kumar AB

4
@Vjay - ви повинні редагувати файл Info.plist у редакторі, не можете встановити ці клавіші в Xcode (станом на бета-версію 6).
Kendall Helmstetter Gelner

11
Просто нагадування, якщо ви не хочете показувати користувачеві роз'яснені користувальницькі пояснення, просто встановіть цей ключ у порожній рядок.
nonamelive

7
Потрібно зберегти свій locationManager, щоб він працював. тому зробіть свій CLLocationManager сильною властивістю
Василь

273
Я "ЛЮБИТЬ", що ви не отримуєте жодної помилки, жодного попередження, жодного повідомлення з журналу, НІЧОГО, якщо ви не залишите запис у списку. В основному Apple створила API-дзвінок, який НІЧОГО не має, якщо у вас немає відповідного списку записів. Дякуємо @OrtwinGentz ​​за те, що це зрозуміло.
MobileVet

314

Я витягнув волосся з тією ж проблемою. Xcode дає вам помилку:

Спроба розпочати MapKitоновлення місцеположення, не вимагаючи авторизації місцезнаходження. Потрібно зателефонувати -[CLLocationManager requestWhenInUseAuthorization]або -[CLLocationManager requestAlwaysAuthorization]спочатку.

Але навіть якщо ви реалізуєте один з перерахованих вище методів, він не підкаже користувачеві, якщо в info.plist для NSLocationAlwaysUsageDescriptionабо немає NSLocationWhenInUseUsageDescription.

Додайте наступні рядки до свого списку info.plist, де значення рядків відображають причину, що вам потрібно отримати доступ до місцезнаходження користувачів

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>

Я думаю, що ці записи, можливо, відсутні, оскільки я почав цей проект у Xcode 5. Я здогадуюсь, що Xcode 6 може додати записи за замовчуванням для цих ключів, але вони не підтверджені.

Більше інформації про ці два Налаштування можна знайти тут


13
xcode 6 не додає ці клавіші за замовчуванням, якщо ви збираєтесь реалізувати CLLocationManager, ви повинні додати їх вручну
Wesley Smith

1
Я також повинен був додати ці вручну, не міг додати через перегляд RawValues ​​info.plist у Xcode6!
Kendall Helmstetter Gelner

1
я вічно дивився на це. Моє повідомлення [CLLLocationManager authorStatus] повертало лише значення <nil>. Після додавання вищевказаних клавіш він почав повертати відповідні перерахування для виводу повідомлень. З того, що я знайшов, це відома помилка iOS 8, але не могла знайти що-небудь у моєму контексті протягом століть. Дякую мілі!
MrOli3000

4
Мені подобається значення рядка, яке ви вводите
Кріс Шен,

1
Повідомлення з’явиться як підповідомлення у Повідомленні, яке запитує, чи бажає користувач поділитися своїм місцезнаходженням. Таким чином, просто бути порожнім (порожнім), мабуть, має найбільш сенс у моїй заяві. Пояснення, чому ви хочете використовувати розташування, також має сенс. Однак NSLocationWhenInUseUsageDescription не поводився так, як очікувалося для мене (тобто. Отримували відмову в дозволі, навіть якщо значення повернення було правильним). NSLocationAlwaysUsageDescription працював чудово.
arcady bob

104

Щоб переконатися, що це сумісність із iOS 7 назад, слід перевірити, чи користувач працює на iOS 8 чи iOS 7. Наприклад:

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

//In ViewDidLoad
if(IS_OS_8_OR_LATER) {
   [self.locationManager requestAlwaysAuthorization];
}

[self.locationManager startUpdatingLocation];

164
Кращий спосіб, ніж перевірка версії, - це перевірити, чи є в об'єкта цей селектор, наприклад: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
progrmr

1
У мене виникли проблеми з просто реалізацією рішення @ progrmr при побудові на Xcode 5, оскільки він не знає, що таке requestAlwaysAuthorizationметод. Моє додаткове рішення було використовувати цю лінію в ifзаяві замість звичайного виклику методу: [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. Можливо, це очевидно для інших людей, але мені знадобилося трохи часу, щоб розібратися. Я думаю, що це правильне рішення, поки не вийде остаточний Xcode 6.
VinceFior

2
Правильне рішення - створити за допомогою Xcode 6. Якщо ви будуєте з Xcode 5, вам не потрібно запитувати авторизацію, це автоматично.
progrmr

У вас може бути точка. Моє занепокоєння полягало в тому, що я хотів, щоб мій код збирався в Xcode 5 (навіть якщо він не працюватиме на iOS 8, якщо не зібраний у Xcode 6), а моя команда переходить на Xcode 6. Але, можливо, це кращий робочий процес, щоб нормально писати код і не зливати його, поки ми не перейдемо до Xcode 6 .. Спасибі.
VinceFior

@VinceFior рекомендований підхід - це умовно компілювати за допомогою визначеного SDK макроса __IPHONE_OS_VERSION_MAX_ALLOWED( #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
Стівен Крамер

50
- (void)startLocationManager
{
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
    [locationManager requestWhenInUseAuthorization]; // Add This Line


}

І до Вашого файлу info.plist введіть тут опис зображення


1
Знайдено подібне рішення більш описовим способом на datacalculation.blogspot.in/2014/11/…
Тест iOS

2
@Hemang: Відповідно до документації Apple Dev: безпечно запускати послуги локації до того, як буде визначено статус авторизації вашого додатка. Хоча ви можете запустити служби локації, ці служби не доставляють ніяких даних, поки статус авторизації не зміниться на kCLAuthorizationStatusAuthorizedAlways або kCLAuthorizationStatusAuthorizedWhenInUse.
Андрій

Трохи запізнюючись, але рекомендую Ви ховати невідповідні частини файлу вашого списку, особливо FacebookAppID
Przemysław Wrzesiński

Дякую Але це лише фіктивний зразок :)
neo D1

Також важливо, щоб проект вказував на правий info.plist (той, де визначено ключ). Це визначено в налаштуваннях збірки проекту в файлі Info.plist File.
ясне світло

30

Згідно з документами Apple:

Станом на iOS 8, у файлі Info.plist додатка потрібне NSLocationWhenInUseUsageDescriptionабо NSLocationAlwaysUsageDescriptionключове значення. Тоді також потрібно запитувати дозвіл у користувача перед реєстрацією на оновлення місцеположення, зателефонувавши [self.myLocationManager requestWhenInUseAuthorization]або [self.myLocationManager requestAlwaysAuthorization]залежно від ваших потреб. Після цього рядок, який ви ввели у Info.plist, відобразиться в діалоговому вікні, що випливає.

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


Простий опис я знайшов тут на datacalculation.blogspot.in/2014/11/…
Тест iOS

28
- (void)viewDidLoad
{

    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
        NSUInteger code = [CLLocationManager authorizationStatus];
        if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
            // choose one request according to your business.
            if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
                [self.locationManager requestAlwaysAuthorization];
            } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
                [self.locationManager  requestWhenInUseAuthorization];
            } else {
                NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
            }
        }
    }
    [self.locationManager startUpdatingLocation];
}

>  #pragma mark - CLLocationManagerDelegate

    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    {
        NSLog(@"didFailWithError: %@", error);
        UIAlertView *errorAlert = [[UIAlertView alloc]
                                   initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [errorAlert show];
    }

    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        NSLog(@"didUpdateToLocation: %@", newLocation);
        CLLocation *currentLocation = newLocation;

        if (currentLocation != nil) {
            longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
            latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
        }
    }

В iOS 8 вам потрібно зробити дві додаткові речі для роботи місця: Додайте ключ до свого Info.plist і запитайте авторизацію у менеджера локації з проханням його запустити. Є два ключі Info.plist для нової авторизації місцезнаходження. Потрібен один або обидва ці клавіші. Якщо жодна з клавіш немає, ви можете зателефонувати startUpdatingLocation, але диспетчер локацій насправді не запуститься. Він також не надішле делегату повідомлення про помилку (оскільки він ніколи не стартував, не може вийти з ладу). Він також не вдасться, якщо ви додасте один або обидва ключі, але забудете явно вимагати авторизації. Отже, перше, що вам потрібно зробити, - це додати один або обидва наступні ключі до файлу Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Обидва ці клавіші беруть рядок

який описує, чому вам потрібні послуги локації. Ви можете ввести рядок типу "Місце знаходження потрібно, щоб дізнатися, де ви знаходитесь", який, як і в iOS 7, може бути локалізований у файлі InfoPlist.strings.

введіть тут опис зображення


19

Моє рішення, яке можна скласти в Xcode 5:

#ifdef __IPHONE_8_0
    NSUInteger code = [CLLocationManager authorizationStatus];
    if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
        // choose one request according to your business.
        if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
            [self.locationManager requestAlwaysAuthorization];
        } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
            [self.locationManager  requestWhenInUseAuthorization];
        } else {
            NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
        }
    }
#endif
    [self.locationManager startUpdatingLocation];

2
Приємне динамічне рішення для використання у всіх додатках. Я б змінив порядок, хоча і замість того, щоб перевірити наявність iphone 8.0, я перевірив би, чи відповідає менеджер локації на авторизацію, а потім запустив авторизацію, щоб отримати код. Це зробить його більш універсальним.
zirinisp

Працював і на xCode 7.2.
Тоторо

17

Старий код запиту про місцезнаходження не працює в iOS 8. Ви можете спробувати цей метод для авторизації місцезнаходження:

- (void)requestAlwaysAuthorization
{
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    // If the status is denied or only granted for when in use, display an alert
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status ==        kCLAuthorizationStatusDenied) {
        NSString *title;
        title = (status == kCLAuthorizationStatusDenied) ? @"Location services are off" :   @"Background location is not enabled";
        NSString *message = @"To use background location you must turn on 'Always' in the Location Services Settings";

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
                                                            message:message
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];
        [alertView show];
    }
    // The user has not enabled any location services. Request background authorization.
    else if (status == kCLAuthorizationStatusNotDetermined) {
        [self.locationManager requestAlwaysAuthorization];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        // Send the user to the Settings for this app
        NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:settingsURL];
    }
}

UIAlertView застаріло. Натомість слід використовувати UIAlertController.
Пасан Премаратне

так, я знаю, що це застаріло, але це також спрацює. але так, краще використовувати UIAlertController для IOS8.
Nits007ak

12

В iOS 8 вам потрібно зробити дві додаткові речі для роботи місця: додайте ключ до свого Info.plist і запитайте авторизацію від менеджера локації з проханням запустити

info.plist:

<key>NSLocationUsageDescription</key>
<string>I need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need location</string>

Додайте це до коду

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

1
незрозуміло, чи ваш псевдокод - препроцесорний або звичайний дзвінок
El Dude

1
Додайте це до файлу constants.h або .pch: #define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] .systemVersion floatValue]> = 8.0)
OxenBoxen

Чому б ви просили обох, вам слід додати коментар, в якому згадується лише використання того чи іншого, залежно від потреб вашої програми
powerj1984

частину info.plist досить легко зробити в Unity3d, але як би я додати кодову частину, якщо використовую юни3d? де?
CthulhuJon

11

Одна поширена помилка для розробників Swift:

Спочатку переконайтеся, що ви додали значення до списку для будь-якого NSLocationWhenInUseUsageDescriptionабо NSLocationAlwaysUsageDescription.

Якщо ви все ще не бачите спливаючого вікна з проханням надати дозвіл, подивіться, чи вводиться рядок var locationManager = CLLocationManager()у viewDidLoadметод перегляду контролера . Якщо ви це зробите, то навіть якщо ви подзвоните locationManager.requestWhenInUseAuthorization(), нічого не з’явиться. Це тому, що після виконання viewDidLoad змінна locationManager розміщується (очищається).

Рішення полягає в тому, щоб знайти рядок var locationManager = CLLocationManager()у верхній частині класового методу.


9

Перед цим [locationManager startUpdatingLocation];додайте запит на послуги локації iOS8:

if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    [locationManager requestAlwaysAuthorization];

Відредагуйте додаток Info.plistі додайте ключ NSLocationAlwaysUsageDescriptionзі значенням рядка, яке відображатиметься користувачеві (наприклад,We do our best to preserve your battery life. )

Якщо вашому додатку потрібні послуги локації лише доки програма відкрита, замініть:

requestAlwaysAuthorizationз requestWhenInUseAuthorizationі

NSLocationAlwaysUsageDescriptionз NSLocationWhenInUseUsageDescription.


9

Я працював над додатком, який було оновлено до iOS 8, і служби локації перестали працювати. Ви, ймовірно, отримаєте помилку в області налагодження так:

Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.

Я зробив найменш настирливу процедуру. Спочатку додайте NSLocationAlwaysUsageDescriptionзапис до свого інформаційного списку:

Введіть тут опис зображення

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

Далі я створив умовний режим для iOS 8:

if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
    [_locationManager requestAlwaysAuthorization];
}

Після цього locationManager:didChangeAuthorizationStatus:метод викликається:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:  (CLAuthorizationStatus)status
{
    [self gotoCurrenLocation];
}

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


7

Рішення із зворотною сумісністю:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}

Налаштування ключа NSLocationWhenInUseUsageDescription у вашому Info.plist


2
Це не правильно, а як щодо випадку kCLAuthorizationStatusDenied? він переходить на інше і починає оновлювати місце, яке не є правильним!
electronix384128

@BenMarten Я не думаю, що це має мати значення. Ви повинні самі впоратися з цим locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error. Однак він забув додати startUpdatingLocation до оператора if, тому після того, як вони його приймуть чи заперечують, він насправді не викликає startUpdateLocation.
Кріс

6

Рішення із зворотною сумісністю, яка не створює попереджень Xcode:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
  [self.locationManager respondsToSelector:requestSelector]) {
((void (*)(id, SEL))[self.locationManager methodForSelector:requestSelector])(self.locationManager, requestSelector);
  [self.locationManager startUpdatingLocation];
} else {
  [self.locationManager startUpdatingLocation];
}

NSLocationWhenInUseUsageDescriptionКлюч налаштування у вашому Info.plist.

Для iOS версії 11.0+ : NSLocationAlwaysAndWhenInUseUsageDescriptionключ налаштування у вашому Info.plist. разом з іншими 2 клавішами.


Це не правильно, а як щодо випадку kCLAuthorizationStatusDenied? він переходить на інше і починає оновлювати місце, яке не є правильним!
electronix384128

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

Виклик [self.locationManager startUpdatingLocation] відразу після запитуWhenInUseAuthorization не має сенсу
Kostia Kim

5

Це проблема з ios 8 Додайте це до коду

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

та до info.plist:

 <key>NSLocationUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationAlwaysUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationWhenInUseUsageDescription</key>
 <string>I need location</string>

NSLocationUsageDescriptionне використовується на iOS8 +
Карлос Рікардо

4

Щоб отримати доступ до місцезнаходження користувача в iOS 8, вам доведеться додати,

NSLocationAlwaysUsageDescription in the Info.plist 

Це попросить у користувача дозволу отримати їх поточне місцезнаходження.


4

Процедура Objective-C Дотримуйтесь наведених нижче інструкцій:

Для iOS-11 Для iOS 11 подивіться цей відповідь: доступ до iOS 11

Потрібно додати два ключі до списку та надати повідомлення, як зображено нижче:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

введіть тут опис зображення Для iOS-10 та нижче:

NSLocationWhenInUseUsageDescription

введіть тут опис зображення

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
    [locationManager requestWhenInUseAuthorization];
}else{
    [locationManager startUpdatingLocation];
} 

Делегатські методи

#pragma mark - Lolcation Update 
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"didFailWithError: %@", error);
    UIAlertView *errorAlert = [[UIAlertView alloc]
                               initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [errorAlert show];
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
        case kCLAuthorizationStatusRestricted:
        case kCLAuthorizationStatusDenied:
        {
            // do some error handling
        }
            break;
        default:{
            [locationManager startUpdatingLocation];
        }
            break;
    }
}
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations lastObject];
    userLatitude =  [NSString stringWithFormat:@"%f", location.coordinate.latitude] ;
    userLongitude =  [NSString stringWithFormat:@"%f",location.coordinate.longitude];
    [locationManager stopUpdatingLocation];
}

Швидка процедура

Дотримуйтесь наведених нижче інструкцій:

Для iOS-11 Для iOS 11 подивіться цей відповідь: доступ до iOS 11

Потрібно додати два ключі до списку та надати повідомлення, як зображено нижче:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

введіть тут опис зображення Для iOS-10 та нижче:

введіть тут опис зображення

import CoreLocation
class ViewController: UIViewController ,CLLocationManagerDelegate {
var locationManager = CLLocationManager()

//MARK- Update Location 
func updateMyLocation(){
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
    if locationManager.respondsToSelector(#selector(CLLocationManager.requestWhenInUseAuthorization)){
       locationManager.requestWhenInUseAuthorization()
    }
    else{
        locationManager.startUpdatingLocation()
    }
}

Делегатські методи

//MARK: Location Update
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
    NSLog("Error to update location :%@",error)
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    switch status {
    case .NotDetermined: break
    case .Restricted: break
    case .Denied:
            NSLog("do some error handling")
        break
    default:
        locationManager.startUpdatingLocation()
    }
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
     let location = locations.last! as CLLocation
    var latitude = location.coordinate.latitude
    var longitude = location.coordinate.longitude

}

Переконайтеся, що також додано NSLocationAlwaysUsageDescription, інакше ви отримаєте помилку під час завантаження в магазин додатків.
Алок

Ваше повідомлення також повинно бути інформативним, інакше яблуко відкине додаток під час поновлення.
Алок

3

Для тих, хто використовує Xamarin , мені довелося додати ключ NSLocationWhenInUseUsageDescriptionдо info.plist вручну, оскільки він не був доступний у спадному меню ні в Xamarin 5.5.3 Build 6, ні в XCode 6.1 - тільки NSLocationUsageDescriptionв списку, і це призвело CLLocationManagerдо продовження промовчати мовчки.


2
        // ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string

        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
        // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
        if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [self.locationManager requestWhenInUseAuthorization];
        }
        [self.locationManager startUpdatingLocation];


    // Location Manager Delegate Methods    
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
        NSLog(@"%@", [locations lastObject]);

}

2

Маленький помічник для всіх вас, хто має більше одного файлу Info.plist ...

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Add NSLocationWhenInUseUsageDescription string' {} 

Він додасть потрібний тег до всіх файлів Info.plist у поточному каталозі (і підпапках).

Інше:

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Set NSLocationWhenInUseUsageDescription $YOURDESCRIPTION' {} 

Це додасть ваш опис до всіх файлів.



2

Я отримую аналогічну помилку в iOS9 (робота з Xcode 7 та Swift 2): намагаюся запустити оновлення місцеположення MapKit, не вимагаючи авторизації місцезнаходження. Потрібно зателефонувати - спочатку [CLLocationManager requestWhenInUseAuthorization] або - [CLLocationManager requestAlwaysAuthorization]. Я дотримувався підручника, але репетитор використовував iOS8 та Swift 1.2. У Xcode 7 та Swift 2 є деякі зміни, я знайшов цей код, і він добре працює для мене (якщо комусь потрібна допомога):

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    // MARK: Properties
    @IBOutlet weak var mapView: MKMapView!

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        self.mapView.showsUserLocation = true

    }

    // MARK: - Location Delegate Methods

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let location = locations.last
        let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
        self.mapView.setRegion(region, animated: true)
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("Errors: " + error.localizedDescription)
    }
}

Нарешті, я помістив це у info.plist: Список інформаційних властивостей: NSLocationWhenInUseUsageDescription Value: Додаток потребує серверів локації для персоналу


2

Щоб отримати доступ до місцезнаходження користувачів в iOS. Потрібно додати два клавіші

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

у файл Info.plist.

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Because I want to know where you are!</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Want to know where you are!</string>

Дивіться це нижче на зображенні.

Зображення Info.plist


1
  1. Додайте ключ NSLocationWhenInUseUsageDescriptionабо NSLocationAlwaysUsageDescription(фонове використання GPS) за допомогою рядка з проханням використовувати GPS для кожної info.plistз цілей.

  2. Попросіть дозволу, запустивши:

    [self initLocationManager: locationManager];

Де initLocationManager:

// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{

    locationManager = [[CLLocationManager alloc]init];

    if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
        [locationManager requestAlwaysAuthorization];
}

Пам’ятайте, що якщо ключі не в info.plistкожній цілі, додаток не запитуватиме користувача. ifЗабезпечує сумісність з прошивкою 7 і respondsToSelector:метод гарантує сумісність в майбутньому , а не тільки вирішення питання для прошивки 7 і 8.


0

Проблема для мене полягала в тому, що клас, який був, CLLocationManagerDelegateбув приватним, що не дозволяло викликати всі делегатські методи. Гадаю, це не дуже поширена ситуація, але я подумав, що я згадаю це у випадку, якщо я нікому не допоможу.


0

Я додаю ці клавіші в InfoPlist.stringsв прошивкою 8.4, IPad міні 2. Це теж працює. Я не встановлюю жодного ключа, як NSLocationWhenInUseUsageDescription, наприклад , у своєму Info.plist.


InfoPlist.strings :

"NSLocationWhenInUseUsageDescription" = "I need GPS information....";

База цього потоку , за його словами as in iOS 7, може бути локалізована в InfoPlist.strings. У моєму тесті ці ключі можна налаштувати безпосередньо у файлі InfoPlist.strings.

Отже, перше, що вам потрібно зробити, - це додати один або обидва наступні> ключі до файлу Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Обидва ці клавіші містять рядок, який описує, чому вам потрібні послуги локації. Ви можете ввести рядок типу "Місце знаходження потрібно, щоб дізнатися, де ви знаходитесь", який, як і в iOS 7 , може бути локалізований у файлі InfoPlist.strings.


ОНОВЛЕННЯ:

Я думаю @IOS, що метод краще. Додайте ключ до Info.plistпорожнього значення та додайте до нього локалізовані рядки InfoPlist.strings.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.