Получение хорошего результата от Core Location за разумное время требует некоторой осторожности.
Проблема в том, что как только вы начнете обновление, didUpdateToLocation
будет срабатывать несколько раз. Каждый раз, когда он стреляет, местоположение должно быть более точным. Однако вы не знаете, сколько раз он сработает, и не знаете, как быстро произойдет блокировка с запрошенной вами точностью (если она когда-либо произойдет). Согласно документации дополнительные события генерируются, если минимальное пороговое расстояние (как указано в свойстве distanceFilter
) превышено или , определяется более точное значение местоположения. Изменение distanceFilter
не даст вам лучшего местоположения (если, конечно, вы не заинтересованы в точных движениях ).
Существуют некоторые общие настройки, которые помогут упростить эту задачу, но вы, вероятно, захотите поиграть с этим в зависимости от желаемой эвристики.
- Установите таймер после отправки
startUpdating
для вызова селектора (может быть просто performSelector:afterDelay:
). Установите максимальную задержку, в течение которой вы готовы ждать разумного приближения. В методе этого селектора я проверю, чтобы убедиться, что местоположение является достаточно точным для размещения в базе данных, и вставлю его. Если это не так, я бы предупредил пользователя.
- В
didUpdateToLocation
немедленно откажитесь от всех слишком старых мест. LocationManager часто сначала возвращает кэшированное значение своего местоположения - и оно может быть очень старым.
- В
didUpdateToLocation
просто сохраните последний результат в переменной экземпляра, если он не соответствует вашей желаемой точности.
- В
didUpdateToLocation
, если новое местоположение достаточно точное, отмените выполнение селектора после задержки и вместо этого немедленно вызовите его.
Это всего лишь грубый набросок, но это довольно универсальная настройка, которую вы можете легко расширить, чтобы получить желаемую функциональность.
Вот основные принципы того, как это может работать. Это парный фрагмент из одного из моих контроллеров представления, чтобы показать основы соответствующих частей:
- (void)viewWillAppear:(BOOL)animated {
[self.locationManager startUpdatingLocation];
[self performSelector:@selector(finishUpdating) withObject:nil afterDelay:10.0];
[super viewWillAppear:animated];
}
- (void) locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
/* Refuse updates more than a minute old */
if (abs([newLocation.timestamp timeIntervalSinceNow]) > 60.0) {
return;
}
/* Save the new location to an instance variable */
self.lastUpdatedLocation = newLocation;
/* If it's accurate enough, cancel the timer */
if (newLocation.horizontalAccuracy < 20.0) {
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(finishUpdating)
object:nil]
/* And fire it manually instead */
[self finishUpdating];
}
}
- (void) finishUpdating {
/* Check the accuracy of self.lastUpdatedLocation, and either
* save it or alert the user that it's not accurate enough */
[self.locationManager stopUpdatingLocation];
}