Службы местоположения не работают в iOS 8: решение проблемы
Решение проблемы, когда CLLocationManager не возвращает координаты и приложение не отображается в настройках iOS 8. Требуемые ключи Info.plist и методы авторизации.
Службы местоположения не работают в iOS 8: приложение не отображается в настройках и CLLocationManager не возвращает координаты
Мое приложение, которое работало корректно на iOS 7, перестало работать после обновления до iOS 8 SDK. Проблема заключается в следующем:
- CLLocationManager не возвращает местоположение
- Приложение не отображается в разделе “Настройки” -> “Службы местоположения”
Я уже пытался найти решение этой проблемы через поиск в Google, но не нашел релевантной информации. Какие возможные причины могут вызывать эту проблему и как ее исправить?
Проблемы с сервисами местоположения в iOS 8 возникают из-за фундаментальных изменений в авторизации местоположения, требующих добавления специальных ключей в Info.plist и вызова методов авторизации перед использованием CLLocationManager. Основная причина, по которой приложение не отображается в настройках и не возвращает координаты, заключается в том, что iOS 8 больше не автоматически запрашивает разрешение на доступ к местоположению без явного запроса от приложения.
Содержание
- Основные проблемы с сервисами местоположения в iOS 8
- Требования к авторизации в iOS 8: ключи Info.plist
- Изменения в CLLocationManager для iOS 8
- Решения для обратной совместимости с iOS 7
- Особенности iOS 11 и новее
- Источники
- Заключение
Основные проблемы с сервисами местоположения в iOS 8
Проблемы с сервисами местоположения в iOS 8 стали одной из самых распространенных сложностей для разработчиков, обновляющих свои приложения с iOS 7. Основная проявляется в двух формах: CLLocationManager не возвращает координаты, а само приложение не отображается в разделе “Настройки” -> “Конфиденциальность” -> “Службы местоположения”. Это происходит из-за фундаментальных изменений в том, как iOS 8 обрабатывает авторизацию доступа к данным местоположения.
В iOS 7 система автоматически запрашивала разрешение у пользователя при первом использовании CLLocationManager. Однако в iOS 8 Apple изменила этот подход, введя явный механизм авторизации. Теперь разработчики должны не только добавить соответствующие ключи в Info.plist, но и явно вызвать методы запроса разрешения перед тем, как начать обновлять местоположение.
Интересно, что если пользователь отклоняет запрос разрешения, приложение не только не получит доступ к местоположению, но и может вообще не отобразиться в настройках системы. Это создает дополнительные сложности при отладке, так как разработчик может не понять, почему его приложение не появляется в списке приложений с доступом к сервисам местоположения.
Требования к авторизации в iOS 8: ключи Info.plist
Для корректной работы сервисов местоположения в iOS 8 необходимо добавить один или два специальных ключа в ваш файл Info.plist. Эти ключи содержат описания, которые будут отображаться пользователю в диалоговом окне запроса разрешения на доступ к местоположению.
Первый обязательный ключ - NSLocationWhenInUseUsageDescription. Этот ключ используется для приложений, которым требуется доступ к местоположению только тогда, когда приложение активно используется пользователем. Значением этого ключа должна быть строка, объясняющая, почему приложению нужен доступ к местоположению. Например: “Это приложение использует ваше местоположение для поиска ближайших магазинов”.
Для приложений, которым необходимо отслеживать местоположение пользователя даже в фоновом режиме, необходимо добавить второй ключ - NSLocationAlwaysUsageDescription. Значение этого ключа должно объяснять пользователю, почему приложению нужен постоянный доступ к местоположению. Например: “Приложению необходимо отслеживать ваше местоположение для отправления уведомлений о приближении к точкам интереса”.
Важно: если вы попытаетесь вызвать методы авторизации без этих ключей в Info.plist, они не сработают, и CLLocationManager не вернет координаты. Более того, приложение может не отображаться в настройках системы, что делает проблему еще более сложной для диагностики.
Для удобства разработки можно добавить оба ключа в Info.plist, даже если приложение использует только один режим авторизации. Это обеспечит гибкость при будущих обновлениях функционала приложения.
Изменения в CLLocationManager для iOS 8
Помимо изменений в Info.plist, в iOS 8 были значительно изменены методы CLLocationManager, связанные с авторизацией. Теперь перед началом обновления местоположения необходимо явно вызвать один из методов запроса разрешения.
Для приложений, которым требуется доступ к местоположению только при активном использовании, следует вызывать метод requestWhenInUseAuthorization(). Этот метод покажет пользователю диалоговое окно с просьбой разрешить доступ к местоположению только тогда, когда приложение активно используется.
Для приложений, которым необходимо отслеживать местоположение в фоновом режиме, следует использовать метод requestAlwaysAuthorization(). Этот запрос покажет пользователю диалоговое окно с просьбой разрешить постоянный доступ к местоположению.
Ключевой момент - эти методы необходимо вызывать до вызова startUpdatingLocation() или startMonitoringSignificantLocationChanges(). Если вы попытаетесь начать обновление местополнения без предварительного запроса разрешения, CLLocationManager не вернет координаты.
Также важно отметить, что в iOS 8 изменились делегаты CLLocationManager. Теперь для обработки состояния авторизации используется свойство authorizationStatus, а не отдельные методы. Вы можете проверить текущий статус авторизации с помощью:
let status = CLLocationManager.authorizationStatus()
Возможные значения статуса:
.notDetermined- пользователь еще не разрешил или запретил доступ.restricted- доступ ограничен родительским контролем или корпоративной политикой.denied- пользователь запретил доступ.authorizedWhenInUse- пользователь разрешил доступ при активном использовании.authorizedAlways- пользователь разрешил постоянный доступ
После вызова метода запроса авторизации, вы должны реализовать делегат locationManager(_:didChangeAuthorizationStatus:) для обработки ответа пользователя.
Решения для обратной совместимости с iOS 7
Поскольку ваше приложение работало на iOS 7, но перестало работать после обновления до iOS 8 SDK, вам необходимо обеспечить обратную совместимость. Это особенно важно, если вы планируете поддерживать устройства под управлением обеих версий iOS.
Для обеспечения совместимости с iOS 7 и iOS 8, вы можете использовать следующий подход:
- Проверьте версию iOS перед вызовом методов авторизации:
if #available(iOS 8.0, *) {
// Код для iOS 8 и новее
locationManager.requestWhenInUseAuthorization()
} else {
// Код для iOS 7 и старше
// Нет необходимости вызывать методы авторизации
}
-
Добавьте оба ключа в Info.plist -
NSLocationWhenInUseUsageDescriptionиNSLocationAlwaysUsageDescription. Это обеспечит работу приложения на всех версиях iOS. -
Реализуйте проверку статуса авторизации перед началом обновления местоположения:
func startLocationUpdates() {
if CLLocationManager.locationServicesEnabled() {
if #available(iOS 8.0, *) {
let status = CLLocationManager.authorizationStatus()
if status == .authorizedWhenInUse || status == .authorizedAlways {
locationManager.startUpdatingLocation()
}
} else {
// Для iOS 7 и старше
locationManager.startUpdatingLocation()
}
}
}
- Реализуйте делегат для обработки изменения статуса авторизации:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse || status == .authorizedAlways {
locationManager.startUpdatingLocation()
}
}
- Убедитесь, что экземпляр CLLocationManager объявлен как strong свойство, чтобы предотвратить его освобождение из памяти:
private var locationManager: CLLocationManager!
- Для отладки в симуляторе XCode измените местоположение: Debug → Location → Apple (или другое значение).
Эти шаги обеспечат корректную работу вашего приложения как на iOS 7, так и на iOS 8 и более новых версиях.
Особенности iOS 11 и новее
В iOS 11 произошли дополнительные изменения в работе сервисов местоположения, которые могут повлиять на ваше приложение. Если вы планируете поддерживать более новые версии iOS, необходимо учесть эти особенности.
В iOS 11 был введен новый ключ в Info.plist - NSLocationAlwaysAndWhenInUseUsageDescription. Этот ключ необходим для приложений, которые хотят использовать как фоновое, так и активное отслеживание местоположения. Хотя для базовой работы можно обойтись без этого ключа, его наличие рекомендуется для корректной работы всех функций.
Для приложений, использующих режим “всегда” (always), в iOS 11 появилась возможность уточнить тип использования фонового отслеживания. Вы можете добавить ключ NSLocationBackgroundLocationUpdateUsageDescription в Info.plist, чтобы предоставить дополнительное объяснение о том, почему вашему приложению необходимо фоновое отслеживание местоположения.
Также в iOS 11 изменился способ обработки запросов авторизации. Теперь система может кэшировать ответ пользователя, и повторные вызовы методов запроса авторизации могут не показывать диалоговое окно. Это означает, что ваше приложение должно быть готово к обработке как разрешенного, так и отклоненного статуса авторизации.
Для отладки в iOS 11 и новее рекомендуется использовать функцию “Simulate Location” в Xcode, которая позволяет эмулировать движения устройства с различными скоростями и типами траекторий.
Если ваше приложение работает неправильно на iOS 11 и новее, проверьте:
- Все ли необходимые ключи добавлены в Info.plist
- Правильно ли обрабатываются статусы авторизации
- Нет ли ошибок в реализации делегатов CLLocationManager
- Правильно ли используется фоновое обновление местополнения
Источники
- Stack Overflow - Location Services Not Working in iOS 8 — Подробное объяснение проблемы с CLLocationManager в iOS 8: https://stackoverflow.com/questions/24062509/location-services-not-working-in-ios-8
- Stack Overflow - CLLocation Manager Not Working iOS 8 — Решение проблемы с CLLocationManager, включая советы по симулятору Xcode: https://stackoverflow.com/questions/29390754/cllocation-manager-not-working-ios-8
- Stack Overflow - CLLocationManager Troubleshooting in iOS 8 — Пошаговое руководство по устранению проблем с CLLocationManager: https://stackoverflow.com/questions/26833695/cllocationmanager-troubleshooting-in-ios-8
- Nevan.net - Core Location Manager Changes in iOS 8 — Обзор изменений в CLLocationManager в iOS 8 от эксперта: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
- Mackuba.eu - Changes to Location Tracking in iOS 11 — Анализ изменений в отслеживании местоположения в iOS 11: https://mackuba.eu/2017/07/13/changes-to-location-tracking-in-ios-11/
Заключение
Проблемы с сервисами местоположения в iOS 8 возникают из-за фундаментальных изменений в механизме авторизации доступа к данным местоположения. Основная причина, по которой приложение не отображается в настройках и не возвращает координаты, заключается в том, что iOS 8 требует явного запроса разрешения через специальные методы CLLocationManager и наличие соответствующих ключей в Info.plist.
Для решения этой проблемы необходимо:
- Добавить ключи
NSLocationWhenInUseUsageDescriptionи/илиNSLocationAlwaysUsageDescriptionв Info.plist с описанием, почему приложению нужен доступ к местоположению - Вывать методы
requestWhenInUseAuthorization()илиrequestAlwaysAuthorization()перед началом обновления местоположения - Реализовать делегат для обработки изменения статуса авторизации
- Обеспечить обратную совместимость с iOS 7 с помощью проверки версии операционной системы
- Для iOS 11 и новее добавить дополнительные ключи в Info.plist при необходимости
Следуя этим рекомендациям, вы сможете восстановить корректную работу сервисов местоположения в вашем приложении на iOS 8 и более новых версиях, сохранив при этом совместимость с iOS 7.
В iOS 8 SDK необходимо вызывать requestAlwaysAuthorization (для фонового местоположения) или requestWhenInUseAuthorization (только для местоположения при работе в активном состоянии) на CLLocationManager перед запуском обновлений местоположения. Также необходимо наличие ключа NSLocationAlwaysUsageDescription или NSLocationWhenInUseUsageDescription в Info.plist с сообщением, которое будет отображаться в запросе. Для обратной совместимости с iOS 7 проверяйте, запущен ли пользователь под iOS 8 или iOS 7.
В симуляторе Xcode необходимо изменить местоположение: Debug → Location → Apple (или другое). Также попробуйте использовать requestAlwaysAuthorization вместо requestWhenInUseAuthorization. Проблема может быть связана с изменениями в iOS 8, как описано в статье http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/.
Убедитесь, что ключи NSLocationWhenInUseUsageDescription и NSLocationAlwaysUsageDescription добавлены в Info.plist. Если приложение не отображается в Настройки → Конфиденциальность → Службы местоположения, это указывает на проблему с plist. Для отладки удалите локализованные значения и оставьте только глобальные. CLLocationManager должен быть объявлен как strong свойство для предотвращения освобождения памяти.
В iOS 8 Core Location больше не автоматически запрашивает разрешение. Чтобы получить координаты, в Info.plist нужно добавить ключ NSLocationWhenInUseUsageDescription (или NSLocationAlwaysUsageDescription) и в коде вызвать requestWhenInUseAuthorization (или requestAlwaysAuthorization) до startUpdatingLocation. После запроса пользователь увидит диалог «Разрешить доступ к местоположению…». Если пользователь отклоняет запрос, приложение не будет отображаться в разделе «Настройки» → «Службы местоположения».
В iOS 11 произошли значительные изменения в отслеживании местоположения. Для приложений, которые непрерывно отслеживают местоположение пользователя, потребуется время для внесения изменений. Для конфигурации авторизации “всегда” для служб местоположения выполните следующие действия: добавьте ключ NSLocationWhenInUseUsageDescription и ключ NSLocationAlwaysAndWhenInUseUsageDescription в ваш файл Info.plist.