Я хочу отслеживать текущее местоположение пользователей только по запросу. Мне нужно только начальное местоположение, а не постоянные обновления. Я подумал, что лучший способ сделать это - отправить пользователю тихое уведомление, чтобы один раз получить текущее местоположение пользователя. Получение тихого уведомления работает нормально, но LocationManager не получает первоначального исправления местоположения. Мой класс Delegate диспетчера местоположений обычно создает экземпляр, но не запускает функцию 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
}
и класс фонового менеджера:
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 полученного удаленного push-уведомления:
"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>
...
Я яростно просматривал SO для подобной проблемы и не смог найти никакого решения, включая этот вопрос:
IOS — запуск фоновой задачи для обновления местоположения пользователя с помощью swift< /а>
Периодические фоновые обновления местоположения iOS
Основное местоположение методы делегирования не вызываются в iOS 8.3 Xcode 6.3.1