Почему расположение [CLLocationManager] не обновляется при отправке сообщения CLLocationManagerDelegate?


Когда сообщение locationManager:didUpdateLocations: (или его устаревший эквивалент locationManager:didUpdateToLocation:fromLocation:) отправляется в CLLocationManagerDelegate, Ссылка на протокол CLLocationManagerDelegate гласит:

К тому времени, когда это сообщение будет доставлено вашему делегату, новый данные о местоположении также доступны непосредственно из CLLocationManager объект. Параметр newLocation может содержать данные, которые были кэшированы из предыдущего использования службы определения местоположения. Вы можете использовать свойство timestamp местоположения объект для определения того, насколько недавно данные о местоположении есть.

Однако на практике СВОЙСТВО CLLocationManager location не обновляется. А почему бы и нет?

Я создал примерный проект, чтобы продемонстрировать это: https://github.com/sibljon/CoreLocationDidUpdateToLocationBug

Соответствующий код находится в JSViewController, фрагмент которого приведен ниже:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
    self.locationManager.distanceFilter = 10000.0; // 10 km
    self.locationManager.delegate = self;
    self.locationManager.purpose = @"To show you nearby hotels.";
    [self.locationManager startUpdatingLocation];

    [self.locationManager startUpdatingLocation];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(appWillEnterForeground:)
                                                 name:UIApplicationWillEnterForegroundNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(appDidEnterBackground:)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    NSLog(@"New location: %@", newLocation);
    NSLog(@"Old location: %@", oldLocation);
    NSLog(@"- [CLLocationManager location]: %@", manager.location);
}

//- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
//{
//    for (CLLocation *location in locations)
//    {
//        NSLog(@"Current location: %@", locations);
//    }
//    NSLog(@"- [CLLocationManager location]: %@", manager.location);
//}

#pragma mark - Notifications

- (void)appWillEnterForeground:(NSNotification *)notification
{
    [self.locationManager startUpdatingLocation];
}

- (void)appDidEnterBackground:(NSNotification *)notification
{
    [self.locationManager stopUpdatingLocation];
}
2 5

2 ответа:

Я считаю, что это ошибка, и я подал сообщение об ошибке в Apple. Зеркало отчета об ошибке можно найти на открытом радаре:

Http://openradar.appspot.com/radar?id=2682402

Как вы прочитали в документации, locationManagerDelegate может доставлять кэшированные данные в метод обратного вызова.

На самом деле это происходит довольно часто, поэтому вам нужно проверить метку времени newLocation против oldLocation или текущего времени, чтобы увидеть, достаточно ли они отличаются (насколько отличаются, зависит от потребностей вашего приложения).

Вот фрагмент того, как вы можете выполнить проверку по текущему времени:

    if ([newLocation.timestamp timeIntervalSinceNow] < 600) // 10 minutes