Как обновить местоположение пользователя по требованию, используя автоматические 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

Swift: местоположение не обновляется при возврате из фона

2 ответа

Я столкнулся с той же самой проблемой и прошел точные шаги как OP безрезультатно. В конце концов я понял, что я только просил CLLocationManager.requestWhenInUseAuthorization() который только обеспечивает местоположение, когда приложение находится на переднем плане. Я должен был просить CLLocationManager.requestAlwaysAuthorization() для того, чтобы приложение запрашивало местоположение в фоновом режиме. Также убедитесь, что у вас есть NSLocationAlwaysUsageDescription вход в Info.plist файл. С этими изменениями я смог использовать CLLocationManager.startUpdatingLocation() напрямую и смог получать обновления местоположения в фоновом режиме.

Когда приложение запускается в фоновом режиме, вызывая startMonitoringSignificantLocationChanges() до startUpdatingLocation() работал на меня.

Не забудьте позвонить stopMonitoringSignificantLocationChanges() а также stopUpdatingLocation() когда вы закончите.

Другие вопросы по тегам