如何为 CLCircularRegion 和 CLBeaconRegion 定义组合进入/退出事件?

How to define combined entry / exit events for both CLCircularRegion and CLBeaconRegion?

我正在监控 iOS 中的 iBeacon 和圆形区域。如果我尝试分别定义它们:

- (void) locationManager:(CLLocationManager *)manager didExitRegion:(CLCircularRegion *)region {}
- (void) locationManager:(CLLocationManager *)manager didExitRegion:(CLBeaconRegion *)region {}

很明显是重复声明错误。 很好地说明了如何区分触发的区域。为了做到这一点,我正在尝试弄清楚如何定义每个人都会满意的公共区域退出事件。如果我使用 CLRegion 组合它们,将会出现各种警告:

- (void) locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    if (region.class == CLCircularRegion.class) {
        CLLocationCoordinate2D coordinate = [region center];  // Deprecation warning, use CLCircularRegion instead
        // etc...
    }
    if (region.class == CLBeaconRegion.class) {
        [locationManager stopRangingBeaconsInRegion:region]; // Incompatible pointer types warning
        // etc...
    }
}

我最初使用 didDetermineState 定义了信标处理,但它会导致一些额外的事件。例如。 CLRegionStateOutside 最初对所有受监控的区域触发,这是完全合适的,但我不需要知道这一点,所以我宁愿使用 didExitRegion 代替。

是否有正确的方法来编写一个干净的组合 didExitRegion 以便它可以处理圆形区域和信标区域而不会出现错误或警告?

方法签名由 CLLocationManagerDelegate 协议定义,并且是:

- (void)locationManager:(CLLocationManager *)manager 
     didExitRegion:(CLRegion *)region;

如果要调用该方法,则必须使用此签名。

检查您通过的区域类型,您的方向是正确的。您缺少的一点是使用强制转换将 region 分配给适当的 subclass 的变量,这样当您尝试 sub-class 时就不会得到 warnings/errors ] 具体的事情。

请注意,使用 isKindOfClass: 比直接比较 class 更安全。 isKindOfClass returns YES 如果对象是指定 class 的实例或指定 class 的子 class。因此,如果 Apple 进行一些内部更改并开始向您发送 CLNewBeaconRegion 对象,该对象是 CLBeaconRegion 的子 class,您的代码仍然有效。

- (void) locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    if ([region isKindOfClass:CLCircularRegion.class]) {
        CLCircularRegion *circularRegion = (CLCircularRegion *)region;
        CLLocationCoordinate2D coordinate = circularRegion.center;
        // etc...
    } else if ([region isKindOfClass:CLBeaconRegion.class]) {
        CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;
        [locationManager stopRangingBeaconsInRegion:beaconRegion];
        // etc...
    }
}