如何提高区域边界跨越精度(模拟)(地理围栏)

时间:2012-04-06 16:07:42

标签: ios geolocation location ios-simulator geofencing

我整理了一个应用程序,当用户离开房子时会触发通知。所以我实现了半径为25的区域监控。 我遇到的问题是在模拟时(iPhone模拟器5.0),我设置了一个自定义位置(home)设置区域边界。然后在区域边界外输入另一个自定义位置,即在街道尽头。但该应用程序并没有注册退出该地区。只有当我设置了家庭位置和地区,然后更改为Apple总部,它会注册并发出通知。 在后台模式下,应用切换到重要的位置更改。但是在前台或后台时它有同样的问题。 我正在寻找什么,比如" Reminders"应用程序,用于应用程序在退出/离开区域边界后很快发出通知,即走到街道的尽头。我如何使其更准确?

这是我的一些viewcontroller.m文件:

- (void)viewDidLoad {
    [super viewDidLoad];

  // Create empty array to add region events to.
  updateEvents = [[NSMutableArray alloc] initWithCapacity:0];

  // Create location manager with filters set for battery efficiency.
  locationManager = [[CLLocationManager alloc] init];
  locationManager.delegate = self;
  locationManager.distanceFilter = kCLLocationAccuracyBest; //could try KLDistanceFilterNone;
  locationManager.desiredAccuracy = kCLLocationAccuracyBest;

  // Start updating location changes.
          [locationManager startUpdatingLocation];
}

- (void)viewDidAppear:(BOOL)animated {
  // Get all regions being monitored for this application.
  NSArray *regions = [[locationManager monitoredRegions] allObjects];

  // Iterate through the regions and add annotations to the map for each of them.
          for (int i = 0; i < [regions count]; i++) {
                    CLRegion *region = [regions objectAtIndex:i];
  RegionAnnotation *annotation = [[RegionAnnotation alloc] initWithCLRegion:region];
                    [regionsMapView addAnnotation:annotation];
                    [annotation release];
          }
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  NSLog(@"didFailWithError: %@", error);
}


- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
  NSLog(@"didUpdateToLocation %@ from %@", newLocation, oldLocation);

  // Work around a bug in MapKit where user location is not initially zoomed to.
          if (oldLocation == nil) {
  // Zoom to the current user location.
                    MKCoordinateRegion userLocation = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 100.0, 100.0);
                    [regionsMapView setRegion:userLocation animated:YES];
          }
}


- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region  {
  NSString *event = [NSString stringWithFormat:@"didEnterRegion %@ at %@", region.identifier, [NSDate date]];

          [self updateWithEvent:event];
}


- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
  NSString *event = [NSString stringWithFormat:@"didExitRegion %@ at %@", region.identifier, [NSDate date]];
          [self updateWithEvent:event];
//implement local notification:
    UIApplication *app                = [UIApplication sharedApplication];
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    [[UIApplication sharedApplication] cancelAllLocalNotifications];

    if (notification == nil)
        return;
    notification.alertBody = [NSString stringWithFormat:@"Did You Lock Your House?"];
    notification.alertAction = @"Lock House";
    notification.soundName = UILocalNotificationDefaultSoundName;
    notification.applicationIconBadgeNumber = 1;
    [app presentLocalNotificationNow:notification];

    [notification release];
// ends here

//following is an alert for the case of exiting boundary whilst app is in foreground
    UIAlertView *alr=[[UIAlertView alloc] initWithTitle:@"Reminder didExitRegion" message:region.identifier delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Ok",nil];

    [alr show];

    [alr release];
    //ends here
}

- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error {
  NSString *event = [NSString stringWithFormat:@"monitoringDidFailForRegion %@: %@", region.identifier, error];

          [self updateWithEvent:event];
}

- (IBAction)addRegion {
  if ([CLLocationManager regionMonitoringAvailable]) {
  // Create a new region based on the center of the map view.
  CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(regionsMapView.centerCoordinate.latitude, regionsMapView.centerCoordinate.longitude);
  CLRegion *newRegion = [[CLRegion alloc] initCircularRegionWithCenter:coord
                                                                                                                                                                              radius:25.0
                                                                                                                                                                   identifier:[NSString stringWithFormat:@"%f, %f", regionsMapView.centerCoordinate.latitude, regionsMapView.centerCoordinate.longitude]];

  // Create an annotation to show where the region is located on the map.
                    RegionAnnotation *myRegionAnnotation = [[RegionAnnotation alloc] initWithCLRegion:newRegion];
                    myRegionAnnotation.coordinate = newRegion.center;
                    myRegionAnnotation.radius = newRegion.radius;

                    [regionsMapView addAnnotation:myRegionAnnotation];

                    [myRegionAnnotation release];

  // Start monitoring the newly created region.
                    [locationManager startMonitoringForRegion:newRegion desiredAccuracy:kCLLocationAccuracyBest];

                    [newRegion release];
          }
  else {
  NSLog(@"Region monitoring is not available.");
          }
}

这项工作来自&#34;地区&#34;模板。

2 个答案:

答案 0 :(得分:6)

对于使用exit / enter进行地理围栏更新,iOS模拟器出了名。您可以解决此问题的一种方法是将应用中的地理围栏设置为您当前的位置。然后,从iOS模拟器的调试菜单中,按位置,然后按高速公路驱动器。您的设备现在将模拟在高速公路上行驶,如果您的模拟器与我的相似,则不会注册didExitRegion事件。

为什么呢?区域主要由Apple的隐藏算法确定,该算法使用Wi-Fi,手机信号塔和手机请求位置的其他应用程序。看作模拟器不使用Wi-Fi或手机信号塔......区域监控将非常不可能。

要测试区域退出后代码的其余部分是否正常工作,您可以创建一个按钮或手动触发您的locationManager:didExitRegion:方法。我还强烈建议您在设备上编译项目,方法是将其插入并从iPhone模拟器更改为iOS设备。然后,您可以拔下设备并从手机上运行应用程序进行测试。

答案 1 :(得分:1)

这是关于你将获得的最佳准确度。区域匹配仅使用细胞塔三角测量,因此在密集区域可能触发50-100m,而稀疏区域可能需要100米。

如果您想要更精细的细节,那么您将需要使用直接位置服务。但这会吃掉电池,所以选择你的毒药。