ConfusedByCode
ConfusedByCode

Reputation: 1730

Is it possible to defer location updates when monitoring significant location changes?

I'm developing an app that monitors significant location changes to get the user's location in the background. I've successfully implemented locationManager.startMonitoringSignificantLocationChanges and the locationManager:didUpdateLocations and locationManager:didFailWithError methods of my CLLocationManagerDelegate.

However, SLC is actually more accurate than I need. According to Apple's docs - and corroborated by my tests - slc triggers a location update roughly every 500m and between 5 and 10 minutes. Therefore, I implemented locationManager.allowDeferredLocationUpdatesUntilTravelled:timeout in my delegate's didUpdateLocations method, as described in this guide: http://apple.co/1W4gqEJ.

Here's my code:

var deferringUpdates = false

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    for location in locations {
        NSLog("Significant location change recorded:\n%@", location)
    }

    if let location = locations.first {
        let secondsAgo: NSTimeInterval = location.timestamp.timeIntervalSinceNow

        // Only process the location if it is very recent (less than 15 seconds old).
        if abs(secondsAgo) < 15.0 {
            saveExtendedUserInfo(withLocation: location)
        }
    }

    if !deferringUpdates {
        manager.allowDeferredLocationUpdatesUntilTraveled(810, timeout: 600)
        deferringUpdates = true
        NSLog("Deferring location updates...")
    }
}

func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
    NSLog(error.localizedDescription)
}

func locationManager(manager: CLLocationManager,
    didFinishDeferredUpdatesWithError error: NSError?)
{
    deferringUpdates = false

    if let deferralError = error {
        NSLog(deferralError.localizedDescription)
    }
}

Unfortunately, the the location manager never defers the updates. Immediately after allowDeferredUpdatesUntilTravelled:timeout is called, the delegate executes didFinishDeferredUpdatesWithError and produces kCLErrorDomain 12, which is CLError.DeferredNotUpdatingLocation.

Why am I getting that error? It seems to mean that the deferred update service doesn't recognize monitoring significant location changes as "updating location". Is it possible to defer the delivery of slc events, or somehow reduce their frequency? If so, how?

Upvotes: 2

Views: 792

Answers (1)

progrmr
progrmr

Reputation: 77271

The purpose of deferring updates is to save battery consumed by the main CPU when processing 1 Hz location updates from the GPS. With deferred updates the CPU stays asleep saving battery while the GPS chip accumulates GPS locations once per second (1 Hz).

With Significant Location Change (SLC) the system is not using the GPS. It is determining location based on cell tower triangulation, which does not wake up the CPU until a significant change has happened.

These two feature are mutually exclusive, you can't defer Significant Location Change's updates because the GPS chip is not involved in SLC.

Upvotes: 5

Related Questions