【问题标题】:Based on user current location Region Monitoring, Delete Monitored Region in iOS7基于用户当前位置Region Monitoring,在iOS7中删除Monitored Region
【发布时间】:2014-02-25 07:55:34
【问题描述】:

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

  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。 如果有人能理解我的问题或有任何建议,请回复。 提前致谢。祝你有美好的一天。

【问题讨论】:

    标签: ios core-location geofencing region-monitoring


    【解决方案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];
    }
    

    【讨论】:

    • 感谢您的评论。我试着这样做。将[manager stopMonitoringForRegion:region]; 放在didExitRegion 方法中,就在[self monitoringRegion]; 之前并进行测试,但它不起作用。 :(
    【解决方案2】:

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

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

    【讨论】:

    • 抱歉回复晚了。感谢您对monitored regions NSSet: 发表我的看法,我认为通过使用uniquely identify,监控也会更加具体和准确。你能告诉我我应该去哪里,或者我该怎么做。如果您可以提供有关此问题的一些链接或教程指南,那将非常有帮助。因为你上面给出的代码对我来说并不完全清楚。再次感谢。保持良好。 :)
    • 嗨。 register 函数来自 Apple 的文档,它非常简单,它将开始监视基于 2 个参数的区域,一个 mkoverlay 和一个 nsstring 标识符。我使用 UUID 只是为了生成一个唯一的字符串。您还有更多工作要做,例如继续跟踪您的监控 ID,以便能够在监控区域 nsset 中找到它们等。
    • 好的,明白了。因为你和它一起工作,我只想问你,在我看来(我在谈论我在帖子中提出的观点)是否有可能完美地完成?现在我所支持的应用程序仍然是简单的 regionMonitoring,它基于用户当前的位置。但它并没有完美地给出准确的ExitRegion 消息。谢谢。
    • IOS 7.1 看起来更准确,但并不完美。在 IOS 7.1 之前,我在当前位置创建的区域有问题,然后第一个出口没有被计算在内,现在看起来还不错。还要注意位置管理器及其委托,didEnter/didExit 最好在共享实例类上声明,这将是 locationmanager 对象的委托。
    • 嘿@CalinChitu 只是想问你这个方法什么时候被调用? - (void)registerRegionWithCircularOverlay:(MKCircle*)overlay andIdentifier:(NSString*)identifier { } 。我正在使用 CoreLocation,并且我已经使用上述 Apple 记录的方法注册了一个区域,但它没有被调用。
    猜你喜欢
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 2012-02-18
    相关资源
    最近更新 更多