iOS 10 个 NSNumber 枚举崩溃

iOS 10 NSNumber crash with enumerations

我有一个非常奇怪的问题,与 NSNumber 对象有关,我的枚举值和在设备 运行 iOS os 版本 10 上访问它们。

Just as a disclaimer - this issue does not happen in other iOS os versions.

我已经像这样声明了一个枚举:

typedef NS_ENUM(NSInteger, MYENUM) {
   FIRST = 1500,
   SECOND = 1700,
   THIRD = 1900,
   ...
};

使用此枚举时,我以这种方式传递它:

[[MyObject alloc] initObjectWith:@(FIRST)];

排除内部逻辑,我在字典中使用枚举,因此需要将其转换为 NSNumber。

这样做时,应用程序崩溃了,因为枚举在某种程度上不是 NSNumber,而是 NSIndexPath。

为什么会这样?

当我删除盒装文字并更改方法签名以接受 NSInteger 时,此崩溃消失。

我曾尝试在网上搜索此类问题,但没有找到。

进一步说明(根据评论)

myObject 的 init 方法内部没有发生特殊逻辑,只是将定义为 NSNumber 的 属性 分配给传递的参数。

关于崩溃日志,Xcode 因提供不太有用的崩溃日志而臭名昭著,我所看到的只是 EXC_BAD_ACCESS,这可能意味着访问已发布的对象或潜在的内存泄漏。

MyObjectclass定义如下:

头文件:

@interface ISNEvent : NSObject

@property(nonatomic, assign) NSNumber* number;

-(instancetype)initObjectWith:(NSNumber*)number;

@end

.m 文件:

- (instancetype)initObjectWith:(NSNumber*)number {
   self = [super init];
   if (self) {
     _number = number;
   }

   return self;
}

您已使用 assign 内存语义定义了 属性:

@property(nonatomic, assign) NSNumber* number;

这意味着您将获得对您提供的任何内容的引用,但您不会保留强引用,并且在对象被释放时您不会 nil 您的引用。这是两全其美的情况,因为您保留了对允许释放的对象的悬空引用。正如您所说,这个特定错误“可能......意味着访问一个已被释放的对象”,而这正是这里发生的事情。

你可以考虑暂时开启僵尸(command+<) 或者“产品”»“方案”»“编辑方案”。 ..”然后转到“运行”设置的“诊断”部分,看看您的行为是否发生变化。您可能不会再看到 NSIndexPath(或其他)引用,而是确认 NSNumber 实例已被释放。

无论如何,您无疑是想将此 NSNumber 属性 设为 strong 参考:

@property(nonatomic, strong) NSNumber *number;

另一个解决方案是使它成为 weak,允许它被释放,但安全地将您的引用设置为 nil。这比 assign 更安全,但我也怀疑这是你的意图。第三种选择是 copy,这是我们有时使用的可变类型,在这里不适用。

归根结底,如今,我建议不要对任何对象类型使用 assign 内存语义。使用 strongcopyweak。在这种情况下,strong 就是您想要的。仅将 assign 用于原始数据类型(例如 NSIntegerCGFloat 等),而不是对象类型。

而且,请记住,当您完成对僵尸的测试后,请关闭该诊断功能。