Местоположение Услуги, не работающие в iOS 8

Мое приложение, работающее отлично на iOS 7, не работает с SDK iOS 8.

CLLocationManager не возвращает местоположение, и я не вижу свое приложение в разделе "Настройки" > "Службы определения местоположения". Я сделал поиск Google по этой проблеме, но ничего не получилось. Что может быть неправильным?

Ответ 1

Я решил решить свою проблему.

По-видимому, в iOS 8 SDK, requestAlwaysAuthorization (для фонового местоположения) или requestWhenInUseAuthorization (местоположение только при переднем плане) требуется вызов CLLocationManager, прежде чем запускать обновления местоположения.

В строке Info.plist также должно быть NSLocationAlwaysUsageDescription или NSLocationWhenInUseUsageDescription с сообщением, которое будет отображаться в подсказке. Добавление этих проблем помогло мне решить.

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

Надеюсь, что это поможет кому-то другому.

EDIT: для получения более подробной информации смотрите: Core-Location-Manager-Changes-in-ios-8

Ответ 2

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

Вы можете найти более подробную информацию об этих двух настройках здесь

Ответ 3

Чтобы обеспечить обратную совместимость с 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];

Ответ 4

- (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 enter image description here

Ответ 5

В соответствии с документами Apple:

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

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

Ответ 6

- (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.

enter image description here

Ответ 7

Мое решение, которое можно скомпилировать в 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];

Ответ 8

Старый код для запроса местоположения не будет работать в 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];
    }
}

Ответ 9

Добавьте это в свой код

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>

Ответ 10

Одна распространенная ошибка для разработчиков Swift:

Сначала убедитесь, что вы добавили значение для plist для NSLocationWhenInUseUsageDescription или NSLocationAlwaysUsageDescription.

Если вы все еще не видите окно, запрашивающее авторизацию, посмотрите, помещаете ли строку var locationManager = CLLocationManager() в свой метод View Controller viewDidLoad. Если вы это сделаете, то даже если вы выберете locationManager.requestWhenInUseAuthorization(), ничего не появится. Это происходит потому, что после выполнения viewDidLoad переменная locationManager освобождается (очищается).

Решение состоит в том, чтобы найти строку var locationManager = CLLocationManager() в верхней части метода класса.

Ответ 11

До [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.

Ответ 12

Я работал над приложением, которое было обновлено до iOS 8, и службы определения местоположения перестали работать. Вероятно, вы получите и ошибку в области отладки, например:

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

Я сделал наименее навязчивую процедуру. Сначала добавьте запись NSLocationAlwaysUsageDescription в свой info.plist:

Enter image description here

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

Далее я создал условие для iOS 8:

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

После этого метод locationManager:didChangeAuthorizationStatus: вызывает вызов:

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

И теперь все работает нормально. Как всегда, посмотрите documentation.

Ответ 13

Решение с обратной совместимостью:

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

Ответ 14

Решение с обратной совместимостью, которое не создает предупреждений 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

Ответ 15

Это проблема с 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>

Ответ 16

Чтобы получить доступ к местоположению пользователя в iOS 8, вам нужно будет добавить

NSLocationAlwaysUsageDescription in the Info.plist 

Это запросит у пользователя разрешение на получение своего текущего местоположения.

Ответ 17

Для тех, кто использует Xamarin, мне пришлось добавить ключ NSLocationWhenInUseUsageDescription в файл info.plist вручную, так как он недоступен в выпадающих списках в Xamarin 5.5. 3 Build 6 или XCode 6.1 - в списке был только NSLocationUsageDescription, и это привело к тому, что CLLocationManager продолжал сбой молча.

Ответ 18

Маленький помощник для всех вас, у которого есть более одного файла 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' {} 

Он добавит ваше описание ко всем файлам.

Ответ 19

        // ** 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]);

}

Ответ 21

Я получаю аналогичную ошибку в 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 Значение: Приложение нуждается в серверах местоположения для персонала

Ответ 22

Чтобы получить доступ к местоположению пользователей в 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

Ответ 23

  • Добавить ключ NSLocationWhenInUseUsageDescription или NSLocationAlwaysUsageDescription (использование фонового GPS) со строкой, запрашивающей использование GPS на каждом info.plist от каждой цели.

  • Запросите разрешение, выполнив:

    [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 обеспечивает совместимость с iOS 7, а метод respondsToSelector: гарантирует будущую совместимость, а не просто решение проблемы для iOS 7 и 8.

Ответ 24

Проблема для меня заключалась в том, что класс, который был CLLocationManagerDelegate, был закрытым, что предотвращало вызов всех методов делегата. Угадайте, что это не очень распространенная ситуация, но я думал, что упомянул об этом, если т поможет кому-нибудь.

Ответ 25

Я добавляю этот ключ в InfoPlist.strings в iOS 8.4, iPad mini 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.


UPDATE:

Я думаю, что метод @IOS лучше. Добавьте ключ в Info.plist с пустым значением и добавьте локализованные строки в InfoPlist.strings.

Ответ 26

Objective-C Процедура Следуйте инструкциям ниже:

Для iOS-11 Для iOS 11 смотрите этот ответ: доступ к местоположению iOS 11

Необходимо добавить два ключа в plist и предоставить сообщение как показано ниже:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription

введите описание изображения здесь Для 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

Необходимо добавить два ключа в plist и предоставить сообщение как показано ниже:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription

введите описание изображения здесь Для 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

}