Подтвердить что ты не робот

Мониторинг текущего местоположения региона не уведомляется при выходе

Я пытаюсь проверить мониторинг области, потому что я получаю текущее местоположение следующим образом:

- (void)startLocationTracking
{
    CLLocationManager *locationManager = [[CLLocationManager alloc] init];

    // Start location manager
    if ([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) {
        locationManager = [LocationTracker sharedLocationManager];
        locationManager.delegate = self;
        [locationManager startMonitoringSignificantLocationChanges];
    }
}

И отслеживание первого местоположения с мониторингом региона следующим образом:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:manager.location.coordinate radius:300 identifier:@"first location initializer"];

        NSLog(@"0: %@", manager.location);
        NSLog(@"1: %@", region);

        [manager startMonitoringForRegion:region];
        NSLog(@"[locationManager startMonitoringForRegion:%@];", region);
    });
}

Затем в каждом выходе из текущей области я отслеживаю новое местоположение следующим образом:

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"%s, %@", __PRETTY_FUNCTION__, region);
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@"%s, %@", __PRETTY_FUNCTION__, region);

    NSArray *allRegions = manager.monitoredRegions.allObjects;

    if (allRegions.count > 0) {
        for (CLRegion *reg in allRegions) {
            [manager stopMonitoringForRegion:reg];
        }
    }

    CLLocationCoordinate2D cord = CLLocationCoordinate2DMake(manager.location.coordinate.latitude, manager.location.coordinate.longitude);
    CLRegion *regionNew = [[CLRegion alloc] initCircularRegionWithCenter:cord radius:300 identifier:@"new region"];

    NSLog(@"region: %@", region);
    NSLog(@"regionNew: %@", regionNew);

    [manager startMonitoringForRegion:regionNew];
}

Я объясню, что я ожидаю:

  • Зарегистрировать текущее местоположение в мониторинге региона.
  • Уведомлять текущую область выхода пользователя.
  • В журнале выхода и повторите регистрацию текущего местоположения как региона.

Этого не происходит.

Где я ошибаюсь?

Я пробовал симулятор с "Freeway Drive".

UPDATE:

Протестировано и работает, из-за ошибки Apple в geofencing, приложение будет поддерживать только 7.1+, довольно плохо, но у меня нет другой идеи.

4b9b3361

Ответ 1

Я думаю, что способ реализации мониторинга региона может вызвать некоторые проблемы.

Вот причины: -

  • Внутри метода startLocationTracking ваш locationManager - это локальный объект, который не распространяется на жизненный цикл этого метода. Это также означает, что каждый раз, когда вы вызываете startLocationTracking, появится новый объект locationManager, который выделяется новым блоком памяти.

    Чтобы решить эту проблему: вы должны использовать singleton locationManager, который является общим locationManager для всего жизненного цикла приложения.

  • Я считаю, что вы не должны startMonitoringForRegion внутри метода делегата -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:. Причина в том, что если вы вызываете startLocationTracking более одного раза, будет более одного locationManager. Несколько диспетчеров местоположений могли отслеживать один и тот же регион, который может вызвать несколько уведомлений.

  • После вызова [manager startMonitoringForRegion:region]; область не будет проверяться немедленно. Если вы не верите мне, попробуйте следующий код: -

    [locationManager startMonitoringForRegion:region];
    NSLog(@"%@",locationManager.monitoredRegions);
    

Вы узнаете, что область, которую вы только что контролировали, не будет находиться внутри locationManager.monitoredRegions. Поскольку это обрабатывается на уровне iOS, поэтому, я думаю, для того, чтобы регион был готов к мониторингу, может потребоваться несколько минут.

Вы также должны понимать другие ограничения для Мониторинга регионов в iOS: -

https://developer.apple.com/library/mac/documentation/CoreLocation/Reference/CLLocationManager_Class/CLLocationManager/CLLocationManager.html

Приложение может регистрировать до 20 регионов за раз. Чтобы сообщить регион меняет своевременно, служба мониторинга региона требует сетевого подключения.

В iOS 6 области с радиусом от 1 до 400 метров работают лучше на iPhone 4S или более поздних устройствах. (В iOS 5 области с радиусом от 1 до 150 метров лучше работают на iPhone 4S и более поздних устройствах.) На этих устройствах приложение может ожидать получить соответствующий регион введенное или выведенное из региона уведомление в течение 3 - 5 минут на средний, если не раньше.

Примечание. Приложения могут ожидать уведомления, как только устройство перемещается на 500 метров или более от предыдущего уведомления. Он не должен ожидать уведомления чаще, чем раз в пять минут. Если устройство может извлекать данные из сети, диспетчер местоположений гораздо чаще доставляет уведомления своевременно.

Я не знаю, что ваше приложение, я считаю, что вы должны перепроектировать поток вашего приложения. Вы должны попытаться контролировать регион за пределами методов делегата.

Для получения дополнительной информации о Синтаксисе LocationManager, вы можете проверить этот ответ: Услуги фонового местоположения, не работающие в iOS 7. В GitHub есть полный проект, содержащий класс Singleton LocationManager, который я назвал LocationTracker.

Вы также можете проверить глюк для мониторинга региона в iOS 7, который я узнал месяц назад (с обходным решением для устранения сбоя): Мониторинг региона Glitch on iOS 7 - Несколько уведомлений одновременно

Ответ 2

Самый удовлетворительный ответ на методы делегатов (didEnterRegion и didExitRegion), которые не вызываются, - это яблочные документы, согласно которым вы будете уведомлены через 3 - 5 минут после входа или выхода, но при фактическом тестировании я обнаружил, что вам нужно подождите около 7-8 минут.

Я тестировал его 10-15 раз, а радиус моей области составлял около 80 метров. Я почесывал голову, чтобы понять, что пошло не так. Я оставил симулятор открытым с отслеживанием местоположения (используется файл gpx для моделирования местоположения). Через 8 минут был вызванExExitRegion.

Также, если вы хотите сделать это в фоновом режиме, вы должны включить фоновые режимы на своей цели. enter image description here