Я сталкиваюсь с очень странной ситуацией с приложением, которое использует CLLocationManager для получения текущего местоположения пользователя.Я использую класс-оболочку, который очень похож на пример кода Apple CLLocationManager.Он начинает поиск местоположения и ждет, пока ему не будет дано местоположение, отвечающее некоторым критериям (возраст отметки времени, точность).Все работает хорошо, когда я нахожусь в очень доступной области GPS.
Теперь вопрос.Когда я нахожусь в моем офисе, на Wi-Fi-соединении, где сигнал GPS кажется паршивым, я открываю свое приложение, и оно никогда не может найти подходящее место.Я выхожу из своего приложения, открываю Foursquare, и он почти сразу находит места рядом со мной, заставляя меня предположить, что он нашел мое местоположение.Я выхожу из Foursquare и снова открываю свое приложение, чтобы найти его почти мгновенно.
Может кто-нибудь пролить свет на то, что здесь может происходить?Я могу опубликовать некоторый код, если люди думают, что это будет полезно, но это более общий вопрос о том, как другие приложения могут положительно или отрицательно влиять на функциональность CLLocationManager.В идеале, я бы хотел знать, что именно Foursquare делает, чтобы получить местоположение так быстро, и как это может привести к тому, что мое приложение вдруг начнет его получать.
РЕДАКТИРОВАТЬ: Судя по приведенному ниже ответу, люди испытали кеширование между приложениями, и это нормально.Однако это не объясняет, почему Foursquare получает местоположение, а мое приложение получает его только после использования Foursquare.Ниже приведен мой код CLLocationManager, надеюсь, кто-нибудь найдет пистолет для курения:
- (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's 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];
}
}
}