iOS 10 NSNumber崩溃,带有枚举

问题描述 投票:1回答:1

我的枚举值与NSNumber对象有关,并在运行iOS操作系统版本10的设备上访问它们时遇到一个非常奇怪的问题。

仅作为免责声明-在其他iOS操作系统版本中不会发生此问题。

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

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

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

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

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

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

Screenshot

为什么会发生?] >>

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

我曾尝试在线搜索这种类型的问题,但是很短。

进一步的说明(每条评论)

] >>

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

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

MyObject类的定义如下:

头文件:

@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;
}

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

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

@property(nonatomic, assign) NSNumber* number;

这意味着您将获得对所提供产品的引用,但是当对象被释放时,您将不会保留很强的引用,也不会nil您的引用。这两个方面的情况都更糟,因为您对允许释放的对象保持悬空的引用。如您所说,此特定错误“可能……意味着访问已释放的对象”,而这恰恰是这里发生的事情。

您可能考虑暂时打开僵尸(

命令

+ <)或“产品”»“方案”»“编辑方案...”,然后转到“运行”的“诊断”部分”设置,然后查看您的行为是否发生了变化。您可能不再会看到NSIndexPath(或其他任何内容)引用,而是会看到NSNumber实例已被释放的确认。无论如何,毫无疑问,您打算将此NSNumber属性设为strong参考:

@property(nonatomic, strong) NSNumber *number;

另一个解决方案是将其设置为weak,允许对其进行重新分配,但请安全地将您的引用设置为nil。这比assign安全,但我也怀疑那是您的意图。第三种选择是copy,这是我们有时用于可变类型的值,此处不适用。

最重要的是,如今,我建议不要对任何对象类型都使用assign内存语义。使用strongcopyweak。在这种情况下,strong是您想要的。仅将assign与原始数据类型(例如NSIntegerCGFloat等)一起使用,而不与对象类型一起使用。

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

enums ios10 nsnumber
1个回答
1
投票
您已经用assign内存语义定义了属性:

@property(nonatomic, assign) NSNumber* number;

© www.soinside.com 2019 - 2024. All rights reserved.