我正在尝试设置一个小型地理围栏(100 米)以在用户离开家时提醒他们。为此,我请求用户的当前位置,如下所示:

- (void)requestUsersCurrentLocation
{
    if (self.locationManager == nil) self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.distanceFilter = 100;
    [self.locationManager startUpdatingLocation];
}

使用 CLLocationManager 的委托(delegate)方法,我检查应用程序是否能够确定用户的当前位置。在我的测试中,这工作正常,应用程序继续调用我的 attemptToRegisterGeofenceAlertForLocation: 方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations lastObject];
    NSDate *eventDate = location.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (abs(howRecent) < 15.0)
    {
        [self.locationManager stopUpdatingLocation];

        if([self attemptToRegisterGeofenceAlertForLocation:location])
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:kGeofenceSetupSuccess object:nil];
        }
        else
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:kGeofenceSetupFailure object:nil];
        }
    }
}

到现在为止还挺好。这是我的自定义函数,用于在用户当前位置周围注册一个相对较小的地理围栏:
- (BOOL)attemptToRegisterGeofenceAlertForLocation:(CLLocation *)location
{
    // Do not create regions if support is unavailable or disabled
    if (![CLLocationManager regionMonitoringAvailable]) return NO;

    // Check the authorization status
    if (([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) && ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusNotDetermined)) return NO;

    // Clear out any old regions to prevent buildup.
    if ([self.locationManager.monitoredRegions count] > 0)
    {
        for (id obj in self.locationManager.monitoredRegions)
        {
            [self.locationManager stopMonitoringForRegion:obj];
        }
    }

    // If the overlay's radius is too large, registration fails automatically,
    // so clamp the radius to the max value.
    CLLocationDegrees radius = 100; // meters?
    if (radius > self.locationManager.maximumRegionMonitoringDistance)
    {
        radius = self.locationManager.maximumRegionMonitoringDistance;
    }

    // Create the region to be monitored.
    CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:location.coordinate radius:radius identifier:kGeofenceIdentifier];
    [self.locationManager startMonitoringForRegion:region];

    return YES;
}

当用户退出地理围栏区域时,我会像这样响应它:
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    if([region.identifier isEqual:kGeofenceIdentifier])
    {
        if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground)
        {
            // Fire a UILocationNotification
        }
        else
        {
            // Fire a UIAlertView
        }
    }
}

我已经确定该应用程序能够获取用户位置并且正确注册了地理围栏,但是我无法在实际设备(支持 3G 的 iPhone)上触发它。我已经离开了地理围栏区域,并在没有收到任何通知的情况下旅行了几英里。通过彻底改变我的位置,我已经成功地在模拟器中收到了警报。

我究竟做错了什么?

最佳答案

看起来您的半径设置为 100M(很好)。距离过滤器也设置为 100M,这可能只是与您作对。在模拟器中,您会获得非常精确的更新,因为您必须将它们传入。在实际测试中,您从 Wifi 近似和单元三角测量中获得的坐标并不精确。

我的经验是,如果我使用 kCLLocationAccuracyBest 作为距离过滤器,我会得到非常好的结果。由于区域监控系统的供电已经很低,因此您不会仅仅通过将过滤器设置为最佳来消耗电池电量。

关于ios - CLLocationManager 的 didExitRegion 永远不会被调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14062468/

10-12 01:41