Tulon
Tulon

Reputation: 4126

Based on user current location Region Monitoring, Delete Monitored Region in iOS7

I am working on such a project where apps do the following things :

  1. User select a radius (10 meter to 1000 meter) and go to next viewController by pressing "Go" button
  2. Here apps Grab users current position and start "region monitoring" based on that current position with selected radius
  3. If the user cross that certain boundary (10 meter to 1000 meter) then it gives an "ExitRegion" alert message. And start "region monitoring" again based on users new current position. And the apps keep doing this all the time, both foreground and background mode. I manage to do it & it is working perfectly.

But now for limitation of the number of region, monitoring by "Region Monitoring", i want to delete every single "monitored region", after it creates new one. So it should happen like :

And it should goes on like this. I am trying this but it is not working properly.

Here is my code :

-(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]];
}

I set flagForRemovingRegion, so that it will not try to delete the "Monitored Region" at the beginning of the apps. Because at the beginning it is NULL. If any one can understand my problem or have any kind of suggestion please reply back. Thanks in Advanced. Have a nice day.

Upvotes: 2

Views: 3038

Answers (2)

Calin Chitu
Calin Chitu

Reputation: 1099

As apple documentation states about monitored regions NSSet:

The objects in this set may not necessarily be the same objects you specified at registration time. Only the region data itself is maintained by the system. Therefore, the only way to uniquely identify a registered region is using its identifier property.

See a sample how I register/manage my regions in my app:

- (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];
             }];

        }
}

And to add a new region:

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

You have to find a way to manage them using the identifier.

Upvotes: 1

beryllium
beryllium

Reputation: 29767

You try to delete first region from NSSet, but actually NSSet is unordered collection, so it's not correct in your case.

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

You have to iterate through this set to find your region or filter it using NSPredicate, but why not to stop it in didExitRegion method?

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

    [manager stopMonitoringForRegion:region];
}

Upvotes: 1

Related Questions