iOS Geofence, как обращаться, когда внутри региона, когда начинается мониторинг?
Мне не удалось разобраться, как справиться со сценарием, когда телефон уже находится внутри региона, когда startMonitoringForRegion
называется? Другие вопросы предложили позвонить requestStateForRegion
внутри didStartMonitoringForRegion
затем вызывается метод didDetermineState: forRegion:
, Итак, код выглядит примерно так:
- (void)viewDidLoad {
//location manager set up etc...
for (Object *object in allObjects){
CLRegion *region = [self geofenceRegion:object];
[locationManager startMonitoringForRegion:region];
}
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager requestStateForRegion:region];
[self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
}
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state == CLRegionStateInside){
[self locationManager:locationManager didEnterRegion:region];
}
}
Теперь, очевидно, метод geofenceRegion - мой собственный, и он отлично работает, и объекты содержат такие вещи, как широта и радиус, и все это тоже хорошо работает, так что это не проблема.
В любом случае, проблема с приведенным выше кодом заключается в том, что он работает, если пользователь уже находится внутри региона, когда он добавляет регион на свое устройство (т. Е. DidEnterRegion завершен). Однако проблема в том, что метод didDetermineState: forRegion:
также вызывается каждый раз, когда одна из граничных областей пересекается согласно Apple Docs:
Диспетчер местоположений вызывает этот метод всякий раз, когда существует пограничный переход для региона. Он вызывает этот метод в дополнение к вызову locationManager:didEnterRegion: и locationManager:didExitRegion: методы. Менеджер местоположений также вызывает этот метод в ответ на вызов его метода requestStateForRegion:, который выполняется асинхронно.
Из-за этого каждый раз, когда вводится регион, didEnterRegion
автоматически вызывается, но затем вызывается снова, потому что didDetermineState: forRegion:
также автоматически вызывается в соответствии с Apple Docs, и это приводит к didEnterRegion
вызывается снова, поэтому регион вводится дважды, когда я хочу, чтобы он вводился только один раз. Как я могу избежать этого?
Спасибо за вашу помощь.
РЕШЕНИЕ
Решение действительно настолько простое, что я просто ошибся. Я должен был выбрать либо использовать 2 метода didEnterRegion:
а также didExitRegion
или использовать didDetermineState: forRegion
и создавать свои собственные методы для входа и выхода из региона, оба не должны использоваться.
Поэтому я решил использовать только didDetermineState: forRegion
метод и мой код теперь выглядит так:
Обратите внимание, что с помощью этого метода регион выхода будет вызываться для региона, если он не находится внутри, и если, как и я, вы хотите, чтобы выход происходил только после того, как ввод произошел, вам понадобится какой-то метод проверки, если регион уже был введен (Я сам использовал основные данные, так как уже использовал их для хранения других аспектов регионов).
- (void)viewDidLoad {
//location manager set up etc...
for (Object *object in allObjects){
CLRegion *region = [self geofenceRegion:object];
[locationManager startMonitoringForRegion:region];
}
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
}
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state == CLRegionStateInside){
[self enterGeofence:region];
} else if (state == CLRegionStateOutside){
[self exitGeofence:region];
} else if (state == CLRegionStateUnknown){
NSLog(@"Unknown state for geofence: %@", region);
return;
}
}
- (void)enterGeofence:(CLRegion *)geofence {
//whatever is required when entered
}
- (void)exitGeofence:(CLRegion *)geofence {
//whatever is required when exit
}
1 ответ
Просто не используйте locationManager:didEnterRegion: вообще, так как locationManager:didDetermineState:forRegion: предоставляет всю необходимую информацию для запуска кода при входе, который, кстати, не должен быть locationManager:didEnterRegion:, используйте ваш собственный селектор, который не является частью протокола CLLocationManagerDelegate.
Другой подход заключается в том, чтобы проверить местоположение внутри региона при начале мониторинга региона. Это решение не так тривиально, как кажется: сначала нужно обновить текущее местоположение, вызвав startUpdatingLocation, так как простое чтение свойства location из locationManager, вероятно, даст вам устаревшее или крайне неточное чтение.