4

我正在尝试设置一个小型地理围栏(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 的委托方法,我检查应用程序是否能够确定用户的当前位置。在我的测试中,这可以正常工作,并且应用程序继续调用我的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)上触发它。我离开了地理围栏区域,走了几英里,却没有收到任何通知。通过彻底改变我的位置,我成功地在模拟器中接收到警报。

我究竟做错了什么?

4

3 回答 3

1

It looks like your radius is set to just 100M (good). The distance filter is also set to 100M as well that might just be fighting against you. In the simulator, you get very precise updates because you have to pass them in. In real world testing, you are getting less than precise coordinates from Wifi approximation and cell-triangulation.

My experience is that if I use kCLLocationAccuracyBest for the distance filter, I get very good results. Since region monitoring is already low powered from the system, you aren't going to take a battery hit just by setting the filter to best.

于 2013-01-02T20:44:31.363 回答
1

事实证明,这个问题的解决方案是确保 CLLocationManager 在主线程上初始化。根据 Apple 的文档:

位置管理器对象的配置必须始终发生在具有活动运行循环的线程上,例如应用程序的主线程。

于 2017-04-30T12:41:47.403 回答
0

你已经得到了你的答案,但有时问题可能是因为没有出去太多,也没有在外面呆太久,或者有时你已经这样做了,但是因为你所在的地区就像设置了一些非常小的东西5 米(你永远不应该做的事情)然后你移动了 100 米

在 iOS 模拟器或设备上测试您的区域监控代码时,请意识到区域事件可能不会在跨越区域边界后立即发生。为了防止虚假通知,iOS在满足某些阈值条件之前不会发送区域通知。具体来说,用户的位置必须跨越区域边界,离开边界最小距离,并在通知报告之前保持在该最小距离至少 20 秒。

具体的阈值距离由硬件和当前可用的定位技术决定。例如, 如果禁用 Wi-Fi,则区域监控的准确性会大大降低。但是,出于测试目的,您可以假设 最小距离约为 200 米

来自Apple 文档:区域监控

于 2017-07-28T14:28:07.813 回答