deferredLocationUpdatesAvailable returns NO in iOS 10
Deferred updates are now officially deprecated (in iOS 13). This is effectively an admission that they have not been supported for several years.
How to get location updates power efficiently with ios when deferredlocationupdatesavailable returns NO
This answer might be a little off, because it is actually not possible anymore to use the deffering functionality even the doc has not been removed. But the intention was to switch on/off the location in intervals to avoid having it on all the time to conserve power.
To getting close to turning on/off completely, one might togge between high and low accuracy, this will save power for sure. (high accuracy typically <10m will use GPS module, low accuracy >500m will typically use AGPS.
First, start an NSTimer with the interval you want, then start updating with high accuracy. When receiving a location in didUpdateLocations, change from high accuracy to low accuracy. The callback of NSTimer requests a new high accuracy location update (ie calls setupHighAccuracy
). The timer thus sets the frequency of the high accuracy updates. This will also work in the background because the location service is still running. If stopping updates, the app will stop in the background. When stopping and at once starting the location manager again, it will immediately call didUpdateLocation, but check the timestamp, the location may be buffered.
Showing some snippets below to get going. Production code will need more filtering and testing:
@property (retain, nonatomic) NSTimer *atimer;
static BOOL _lowAccuracy;
- (void)timerCallback {
[self setupHighAccuracy];
}
- (void)setupTimer
{
if(self.atimer != nil)
{
return;
}
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTaskId =
[app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTaskId];
bgTaskId = UIBackgroundTaskInvalid;
}];
dispatch_async( dispatch_get_main_queue(), ^{
self.atimer = [NSTimer scheduledTimerWithTimeInterval:15.0 // consider higher interval
target:self
selector:@selector(timerCallback)
userInfo:nil
repeats:YES];
}
[app endBackgroundTask:bgTaskId];
bgTaskId = UIBackgroundTaskInvalid;
});
}
- (void)setupHighAccuracy
{
if(_lowAccuracy)
{
[_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; // or kCLLocationAccuracyBest, tune yourself
_locationManager.activityType = CLActivityTypeFitness;
_locationManager.distanceFilter = 15; // or 0, tune yourself
_lowAccuracy = false;
[_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
}
}
- (void)setupLowAccuracy
{
if(!_lowAccuracy)
{
s_initialized = true;
[_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
_locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
_locationManager.activityType = CLActivityTypeFitness;
_locationManager.distanceFilter = 3000;
_lowAccuracy = true;
[_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
CLLocation *location = locations.lastObject;
if(!_lowAccuracy) {
// update system with location here
[_locationManager.delegate setupLowAccuracy];
self.s_lastLocation = location;
}
}
iOS 11 deferredLocationUpdatesAvailable always return NO and Error Domain=kCLErrorDomain Code=11. How to make deferredlocationupdates work?
Unfortunatly, despite of all documentation and after weeks of frustrating development effort, I excepted the fact, that this functionality is not supported anymore. I tested it in all possible situations on 7 different real devices (iPads and iPhones, 5s up to 7) ... no success.
It did work perfectly on IOS 9, this is why I trust, that I know how to do it. But I tried every hint I found here and elsewere... no success under IOS 10 and 11.
If you look around you will find numerous angry comments from other coder. It‘s a shame, but we have to except the facts.
CLError.DeferredFailed Error (kCLErrorDomain Code=11) Deferred GPS Updates Failing
iOS 9.2, Xcode 7.2, ARC enabled
The problem is most likely associated with the distance and time interval you have chosen for your deferral. Try to take advantage of CLLocationDistanceMax
and CLTimeIntervalMax
to troubleshoot the function call. For example, set the distance to CLLocationDistanceMax
and then vary the time interval, then try vice versa.
But there are other things I see that you might want to change...
- Get rid of
CLLocationManager.deferredLocationUpdatesAvailable() == true
condition in the if statements to allow deferred location updates. - Deferred updates were available iOS6.0+, most iPhone 4S can be updated to iOS7.2.1 depending on the hardware. You do not need to separately call
_locationManager.startUpdatingLocation()
. - Make sure that if you are testing in iOS9.0+ that you have the
allowsBackgroundLocationUpdates
set for the location manager. - Make sure that the initial
_locationManager.startUpdatingLocation()
is made in the- (void)applicationWillResignActive:(UIApplication *)application
method equivalent in Swift and NOT in the- (void)applicationDidEnterBackground:(UIApplication *)application
method. - Make sure that you are calling
_locationManager.allowDeferredLocationUpdatesUntilTraveled(C_GPS.ACTIVITY_UPDATE_DISTANCE, timeout: C_GPS.ACTIVITY_UPDATE_TIME)
in the equivalent of the- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
method for Swift.
Also, note that you are printing the error before you check if the error exists, this might lead to some incorrect error reporting.
Hope this helps and I am not too late! Cheers.
P.S. If this doesn't work, then please post more of your code, i.e. where you are calling these functions in relation to the app. delegate *.m file.
Related Topics
Open Installed Pwa from External Url
How to Deserialize an Escaped JSON String with Nsjsonserialization
Avspeechsynthesizer Output as File
Determinate Finish Loading Website in Webview with Swift in Xcode
Is This Code Drawing at the Point or Pixel Level? How to Draw Retina Pixels
Swift - Fatal Error: Array Index Out of Range
Avoid Animation of Uicollectionview After Reloaditemsatindexpaths
Swift 3.0 Result of Call Is Unused
Corebluetooth: What Is the Lifetime of Unique Uuids
How to Identify iOS Device Uniquely
How to Use Unsafemutablepointer in Swift 3
How to Broadcast Multiple Ibeacon Signals from Only One Bluetooth? and How