EXC_BAD_ACCESS 将 CLBeacon 设置为 nil 时

EXC_BAD_ACCESS when setting a CLBeacon to nil

以下将CLBeacon设置为nil时会执行崩溃。

CLBeacon *beacon = [[CLBeacon alloc] init];
beacon = nil; // crash

是否无法释放已初始化的 CLBeacon


这可以通过简单地将上面的代码添加到 App Delegate 的 didFinishLaunchingWithOptions

中的新项目来重现
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    CLBeacon *beacon = [[CLBeacon alloc] init];
    beacon = nil; // crash
    return YES;
}

CLBeacon 的苹果文档指出:

You do not create instances of this class directly. The location manager object reports encountered beacons to its associated delegate object.

它崩溃的原因是一个并不重要的实现细节,但这是因为当您调用 initCLBeacon 没有正确初始化。当它解除分配时,CLBeacon 取消引用它的 _internal ivar,如果它是 NULL.

则崩溃

您可以通过在调试器中查看 CLBeacon->_internal ivar 的值来了解这一点。如果您使用 init 创建信标,则 ivar 为 NULL,但如果您使用 [[CLBeacon alloc] initWithCoder:nil] 创建它,它将有一个值,并且当您将信标设置为 nil.

运行 在使用模拟 subclass 时遇到这个问题。每次 ARC 释放模拟的 subclass 时,我的测试都会崩溃。

解决方法是在CLBeacon 上调用正确的init 方法。 查看 here 我们看到有一个附加的 init 方法。在代码中的类别中声明它。

@interface CLBeacon (PRXInternal)

- (id)initWithProximityUUID:(id)arg1 major:(id)arg2 minor:(id)arg3 proximity:(long long)arg4 accuracy:(double)arg5 rssi:(long long)arg6 ;

@end

如果您需要 class 的实例,请调用此初始化程序。不包含在生产代码中。