На основе текущего местоположения пользователя Мониторинг региона, Удалить контролируемый регион в iOS7

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

  1. Пользователь выбирает радиус (от 10 до 1000 метров) и переходит к следующему viewController, нажав кнопку "Перейти"
  2. Здесь приложения захватывают пользователей текущую позицию и запускают "мониторинг региона" на основе этой текущей позиции с выбранным радиусом
  3. Если пользователь пересекает эту определенную границу (от 10 до 1000 метров), он выдает предупреждающее сообщение "ExitRegion". И снова запустить "мониторинг региона" на основе новой текущей позиции пользователя. И приложения продолжают делать это все время, как на переднем плане, так и в фоновом режиме. Мне удается это сделать, и это работает отлично.

Но теперь для ограничения количества регионов, отслеживаемых "Region Monitoring", я хочу удалить каждый "отслеживаемый регион" после того, как он создаст новый. Так должно получиться так:

  • Начать мониторинг региона на основе текущей позиции пользователей
  • Выйти из определенного региона и получить предупреждение "Выйти из региона"
  • Удалить этот "Контролируемый регион" из stopMonitoringForRegion массив
  • Начать заново Регион Мониторинг на основе текущей позиции пользователей
  • Выйти из определенного региона и получить предупреждение "Выйти из региона"
  • Удалить этот "Контролируемый регион" из stopMonitoringForRegion массив

И так должно продолжаться. Я пытаюсь это, но это не работает должным образом.

Вот мой код:

-(void)startLocationServices
{
    if (self.locationManager == nil)
    {
        self.locationManager = [CLLocationManager new];
    }
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager setDelegate:self];
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
    //[self.locationManager startUpdatingLocation];
}

-(void) monitoringRegion
{
    if (flag == 0)
    {
        if (flagForRemovingRegion == 1)
        {
            // Remove monitored region from "monitoredRegions" array after monitor 5 regions
            [self removingMonitoredRegion];
        }

        CLLocationCoordinate2D center = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude);

        CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center radius:myval identifier:@"Test"];
        CLLocationDegrees radius = myval;

        if (radius > self.locationManager.maximumRegionMonitoringDistance)
        {
            radius = self.locationManager.maximumRegionMonitoringDistance;
        }
        [self.locationManager startMonitoringForRegion:region];

        flag = 1;
        flagForRemovingRegion = 1;
        self.availabilityTextView.text = [@"Your selected Radius:" stringByAppendingFormat:@"%i", self.myval];
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    flag = 0;
    [self startLocationServices];
    [self monitoringRegion];
}

-(void) removingMonitoredRegion
{
    [locationManager stopMonitoringForRegion:[[[locationManager monitoredRegions] allObjects] objectAtIndex:0]];


}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
//    // regions are stored by system
    self.threeTextView.text = [@"Regions: \n\n" stringByAppendingFormat:@"%@", [[self.locationManager monitoredRegions] allObjects]];

    UIAlertView *alertViewOne = [[UIAlertView alloc] initWithTitle:@"Status" message:@"Region Monitoring started." delegate:self cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];

    [alertViewOne show];
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    UIAlertView *alertViewTwo = [[UIAlertView alloc] initWithTitle:@"Status" message:@"You Enter the region" delegate:self cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];

    [alertViewTwo show];
    self.availabilityTextView.text = @"You enter the region!";
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    UIAlertView *alertViewThree = [[UIAlertView alloc] initWithTitle:@"Status" message:@"You Exit the region" delegate:self cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];

    [alertViewThree show];
    flag = 0;
    self.availabilityTextView.text = @"You exit the region!";
    [self monitoringRegion];
}

- (void) locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
    self.availabilityTextView.text = [@"\nError:" stringByAppendingFormat:@"%@", [error localizedDescription]];
}

Я поставил flagForRemovingRegion, так что он не будет пытаться удалить "Отслеживаемый регион" в начале приложений. Потому что в начале это NULL. Если кто-то может понять мою проблему или есть какие-либо предложения, пожалуйста, ответьте. Заранее спасибо. Хорошего дня.

2 ответа

Вы пытаетесь удалить первый регион из NSSet, но на самом деле NSSet является неупорядоченной коллекцией, поэтому это не правильно в вашем случае.

[locationManager stopMonitoringForRegion:[[[locationManager monitoredRegions] allObjects] objectAtIndex:0]];

Вы должны перебрать этот набор, чтобы найти свой регион или отфильтровать его с помощью NSPredicate, но почему бы не остановить его в didExitRegion метод?

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    // your code here

    [manager stopMonitoringForRegion:region];
}

В яблочной документации говорится об отслеживаемых регионах NSSet:

Объекты в этом наборе не обязательно должны быть теми же объектами, которые вы указали при регистрации. Только данные о регионе поддерживаются системой. Поэтому единственный способ однозначно идентифицировать зарегистрированный регион - использовать его свойство идентификатора.

Посмотрите пример того, как я регистрирую / управляю моими регионами в моем приложении:

- (void)registerRegionWithCircularOverlay:(MKCircle*)overlay andIdentifier:(NSString*)identifier {

    // If the overlay's radius is too large, registration fails automatically,
    // so clamp the radius to the max value.
    CLLocationDegrees radius = overlay.radius;
    if (radius > sharedInst.locationManager.maximumRegionMonitoringDistance) {
        radius = sharedInst.locationManager.maximumRegionMonitoringDistance;
    }
    // Create the geographic region to be monitored.
    CLCircularRegion *geoRegion = [[CLCircularRegion alloc]
                                   initWithCenter:overlay.coordinate
                                   radius:radius
                                   identifier:identifier];
    if([CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]])
        if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized){
            NSLog(@"we can monitor");
            Region* reg = [[Region alloc] init];
            reg.myRegion = geoRegion;
            [sharedInst.regionsDict setObject:reg forKey:identifier];
            [sharedInst.locationManager startMonitoringForRegion:geoRegion];

            CLGeocoder *coder = [[CLGeocoder alloc]init] ;
            CLLocation *myLocation = [[CLLocation alloc]initWithLatitude:geoRegion.center.latitude longitude:geoRegion.center.longitude];

            [coder reverseGeocodeLocation:myLocation completionHandler:
             ^(NSArray *placemarks, NSError *error){
                 CLPlacemark *placemark= [placemarks objectAtIndex:0];
                 reg.myName = [NSString stringWithFormat:@"%@, %@", placemark.locality, placemark.thoroughfare];
                 NSLog(@"we did monitor: %@", reg.myName);
                 [sharedInst saveData];
             }];

        }
}

И добавить новый регион:

   NSString* locId = [NSString stringWithFormat:@"KCC: %@", [[NSUUID UUID] UUIDString]];
   [self registerRegionWithCircularOverlay:circleOverlay andIdentifier:locId];

Вы должны найти способ управлять ими, используя идентификатор.

Другие вопросы по тегам