Как обновить местоположение пользователя по требованию, используя автоматические push-уведомления? IOS
Я хочу отслеживать текущее местоположение пользователей только по запросу. Мне нужно только начальное местоположение, а не непрерывные обновления. Я подумал, что лучший способ сделать это - отправить пользователю молчаливое уведомление, чтобы узнать текущее местоположение пользователя один раз. Получение молчаливого уведомления работает просто отлично, но LocationManager не получает первоначальное исправление для местоположения. Мой делегат Location Manager обычно создает экземпляр, но не запускает функцию didUpdateLocations в любой момент после вызова метода менеджера местоположения startUpdatingLocation(). Когда приложение запускается нормально из AppDelegate:didFinishLaunchingWithOptions, LocationManager обновляет местоположение пользователя без проблем.
Я разрабатываю на Xcode 6.3.2 для iOS 8.3
Мой AppDelegate:DidReceiveRemoteNotification выглядит так:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
var bgTask = bgManager()
bgTask.registerBackgroundTask()
LocManager.locationMngr.startUpdatingLocation() // LocManager is global variable
let delayInSeconds = 8.0
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue()) {
println(LocManager.updated)
bgTask.endBackgroundTask()
handler(UIBackgroundFetchResult.NewData)
}
}
Я сначала попробовал только со строкой:
LocManager.locationMngr.startUpdatingLocation()
но когда это не сработало, я добавил фоновую задачу и dispatch_after, чтобы убедиться, что у моего менеджера местоположений будет достаточно времени для получения первого обновления местоположения до завершения.
Вот класс LocationManager:
class LocationManager: NSObject, CLLocationManagerDelegate {
let locationMngr:CLLocationManager
var coord:CLLocationCoordinate2D
var updated:Bool
override init() {
locationMngr = CLLocationManager()
coord = CLLocationCoordinate2D()
updated = false
super.init()
locationMngr.delegate = self
locationMngr.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationMngr.startUpdatingLocation() //Should call didUpdateLocations after some time
}
//Doesn't get called in AppDelegate remoteNotifications method
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
{
var loc:CLLocation = locations.first as! CLLocation
self.coord = loc.coordinate
locationMngr.stopUpdatingLocation()
updated = true
}
и класс Background Manager:
class bgManager:NSObject{
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
override init(){
super.init()
}
func registerBackgroundTask() {
backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
[unowned self] in
self.endBackgroundTask()
}
}
func endBackgroundTask() {
UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
}
JSON полученного удаленного нажатия:
"aps" : {
"sound" : "",
"content-available" : 1,
"priority" : 5
}
У меня есть все необходимые ключи plist.info и фоновые режимы для извлечения, уведомлений и местоположения, включенные в проекте Возможности: Фоновые режимы. фрагмент plist.info:
<dict>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>location-services</string>
<string></string>
<string></string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
<string>fetch</string>
<string>location</string>
</array>
<key>NSLocationAlwaysUsageDescription</key>
<string>Your location is needed for this app.</string>
...
Я яростно просмотрел схожую проблему и не смог найти никакого решения, включая этот вопрос:
IOS - Запуск фоновой задачи для обновления местоположения пользователя с помощью swift
Периодические обновления фона iOS
Базовые методы делегата Местоположения, не вызываемые в iOS 8.3 Xcode 6.3.1
2 ответа
Я столкнулся с той же самой проблемой и прошел точные шаги как OP безрезультатно. В конце концов я понял, что я только просил CLLocationManager.requestWhenInUseAuthorization()
который только обеспечивает местоположение, когда приложение находится на переднем плане. Я должен был просить CLLocationManager.requestAlwaysAuthorization()
для того, чтобы приложение запрашивало местоположение в фоновом режиме. Также убедитесь, что у вас есть NSLocationAlwaysUsageDescription
вход в Info.plist
файл. С этими изменениями я смог использовать CLLocationManager.startUpdatingLocation()
напрямую и смог получать обновления местоположения в фоновом режиме.
Когда приложение запускается в фоновом режиме, вызывая startMonitoringSignificantLocationChanges()
до startUpdatingLocation()
работал на меня.
Не забудьте позвонить stopMonitoringSignificantLocationChanges()
а также stopUpdatingLocation()
когда вы закончите.