Could other applications be affected by CLLocationManager?

I came across a very strange situation with an application that I have that uses the CLLocationManager to get the user's current location. I use a shell class that is very similar to the Apple CLLocationManager example code. He begins to search for a location, and he waits until he is given a place that meets certain criteria (age, timeline, accuracy). Everything works well when I am in a very accessible GPS zone.

Now the problem. When I’m in my office, on a Wi-Fi connection, where the GPS signal is apparently lousy, I open the application and I will never find a suitable place. I exit my application, open Foursquare, and it almost immediately discovers the places near me, suggesting that he found my location. I exit Foursquare and reopen the application to find that it finds my location almost instantly.

Can anyone shed light on what can happen here? I can publish the code if people think that it will be useful, but this is a more general question about how other applications can positively or negatively affect the functionality of CLLocationManager. Ideally, I would like to know what Foursquare is doing to quickly find a place, and how it can make my application suddenly start receiving it.

EDIT: It seems that, based on the answer below, people are faced with cross-application caching, and that's fine. However, it does not explain why Foursquare gets the location, and my application only gets it after using Foursquare. Below is my CLLocationManager code, hope someone can find a smoking weapon:

- (void) lazyInit { if (!self.locationManager) { self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; self.reverseGeocoder = [[WPGeocodingService alloc] initWithDelegate:self]; self.locationAndPlacemark = NO; } } - (void) getCurrentLocation { [self lazyInit]; self.recentLocation = nil; [self performSelector:@selector(timeoutLocationFetch) withObject:nil afterDelay:kLocationFetchTimeout]; [self.locationManager startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSLog(@"LocationService:update: <%f,%f> Accuracy: %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude, newLocation.horizontalAccuracy); // test the age of the location measurement to determine if the measurement is cached // in most cases you will not want to rely on cached measurements NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow]; if (locationAge > 5.0) return; // test that the horizontal accuracy does not indicate an invalid measurement if (newLocation.horizontalAccuracy < 0) return; // test the measurement to see if it is more accurate than the previous measurement if (self.recentLocation == nil || self.recentLocation.horizontalAccuracy > newLocation.horizontalAccuracy) { // store the location as the "best effort" self.recentLocation = newLocation; // test the measurement to see if it meets the desired accuracy // // IMPORTANT!!! kCLLocationAccuracyBest should not be used for comparison with location coordinate or altitidue // accuracy because it is a negative value. Instead, compare against some predetermined "real" measure of // acceptable accuracy, or depend on the timeout to stop updating. This sample depends on the timeout. // if (newLocation.horizontalAccuracy <= self.locationManager.desiredAccuracy) { // we have a measurement that meets our requirements, so we can stop updating the location // // IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible. // [self.locationManager stopUpdatingLocation]; // we can also cancel our previous performSelector:withObject:afterDelay: - it no longer necessary [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeoutLocationFetch) object:nil]; if ([self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) { [self.delegate locationService:self didReceiveLocation:self.recentLocation]; } } } } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"LocationService:error: %@", [error description]); if ([error code] != kCLErrorLocationUnknown) { [self.locationManager stopUpdatingLocation]; if ([self.delegate respondsToSelector:@selector(locationService:didFailWithError:)]) { [self.delegate locationService:self didFailWithError:error]; } } } - (void) timeoutLocationFetch { NSLog(@"LocationService:timeout"); [self.locationManager stopUpdatingLocation]; if (self.recentLocation && [self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) { if ([self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) { [self.delegate locationService:self didReceiveLocation:self.recentLocation]; } } else { NSError* error = [NSError errorWithDomain:@"Location Error" code:0 userInfo: [NSDictionary dictionaryWithObject:@"The application could not determine your location." forKey:NSLocalizedDescriptionKey]]; if ([self.delegate respondsToSelector:@selector(locationService:didFailWithError:)]) { [self.delegate locationService:self didFailWithError:error]; } } } 
+4
source share
2 answers

Why are you using

 self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters 

not kCLLocationAccuracyBest ? Of course, without comparing horizontal accuracy with this, as you noticed, a negative constant - but some reasonable other value (say, 100.0 m). Have you tried, does it matter?

The required accuracy controls how much effort is applied to capturing a position (for higher GPS values ​​it’s not even turned on, as you can check with Xcode / Instruments / EnergyDiagnostics). Less effort leads to a decrease in accuracy and / or an increase in the time required to obtain a position. Isn't that wise?

From my own observations: when iOS is requested for a position with a certain desired accuracy, the result can be anything: less accurate (that is, in a building with poor GPS reception), as necessary, or actually more accurate than (another application or another the CLlocationManager object of the same application can simultaneously request hardware with greater accuracy - then all other applications inherit better values ​​without additional effort).

In addition to the above, it may matter whether your iOS device has access to the Internet, as it is an auxiliary GPS receiver. There may be some side effect when some supporting data is downloaded if the device is online due to some other activity on the Internet. However, this last thought is pure speculation.

One more thing: If I did not miss this in your code, then you did not define a distance filter. Try something like

 self.locationManager.distanceFilter = kCLDistanceFilterNone; 

to provide as many updates as possible.

+1
source

yes, I think CLLocationManager caches the location to some extent, I tried several things, for example, launching GoogleGaps, my location was found, and then my application started, it immediately found my location. I also tried, launched the navigation application, found my location, killed him immediately, launched other applications that use location, all applications can instantly detect a lock in the location.

0
source

Source: https://habr.com/ru/post/1392064/


All Articles