2

我正在从事这样一个项目,其中应用程序执行以下操作:

  1. 用户选择一个半径(10 米到 1000 米)并按“Go”按钮转到下一个 viewController
  2. 这里的应用程序抓取用户当前位置并基于选定半径的当前位置开始“区域监控”
  3. 如果用户越过该特定边界(10 米到 1000 米),则它会发出“ExitRegion”警报消息。并根据用户新的当前位置再次启动“区域监控”。并且应用程序一直在这样做,无论是前台模式还是后台模式。我设法做到了,并且运行良好。

但是现在为了限制区域数量,通过“区域监控”进行监控,我想在创建新区域后删除每个“监控区域”。所以它应该像这样发生:

  • 根据用户当前位置启动区域监控
  • 退出特定区域并收到“退出区域”警报消息
  • 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。如果有人能理解我的问题或有任何建议,请回复。先谢谢了。祝你今天过得愉快。

4

2 回答 2

1

正如苹果文档中关于受监控区域 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];

您必须找到一种使用标识符来管理它们的方法。

于 2014-02-25T08:13:57.957 回答
1

您尝试从 NSSet 中删除第一个区域,但实际上 NSSet 是无序集合,因此在您的情况下不正确。

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

您必须遍历此集合以找到您的区域或使用 NSPredicate 对其进行过滤,但为什么不在didExitRegion方法中停止它呢?

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

    [manager stopMonitoringForRegion:region];
}
于 2014-02-25T08:08:55.437 回答