我有一个非常奇怪的问题,与 NSNumber
对象,并在运行 iOS os 10 版本的设备上访问它们。
在此声明一下--这个问题不会发生在其他iOS os版本上。
我已经声明了一个枚举,就像这样。
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
,这可能意味着访问一个已经被释放的对象或潜在的内存泄漏。
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;
}
你已经定义了你的属性 assign
内存语义。
@property(nonatomic, assign) NSNumber* number;
这意味着,你会得到一个引用到你提供的任何东西, 但你不会保持一个强大的参考,你不会。nil
当对象被deallocated时,你的引用就会被删除。这是两全其美的事情,因为你对一个允许被deallocated的对象保留了一个悬而未决的引用。正如你所说,这个特殊的错误 "可能......意味着访问一个已经被释放的对象",而这正是这里发生的事情。
你可以考虑暂时打开僵尸 (指挥+<)或 "产品"" "方案"" "编辑方案...",然后进入 "运行 "设置的 "诊断 "部分,看看你的行为是否发生了变化。你可能不会再看到 NSIndexPath
(或其他什么)的提法,而是在某种程度上证实了这一点。NSNumber
实例已被重新分配。
无论如何,你无疑是想让这个 NSNumber
财产a strong
参考。
@property(nonatomic, strong) NSNumber *number;
另一个解决办法是使其 weak
,允许它被重新分配,但安全地将您的引用设置为 nil
. 这比安全 assign
但我也怀疑这是不是你的意图。第三种选择是 copy
这就是我们有时在可变类型中使用的东西,但在这里并不适用。
一句话,现在,我建议永远不要使用 assign
内存语义与任何对象类型。使用 strong
, copy
或 weak
. 在这种情况下: strong
是你想要的。只使用 assign
与原始数据类型(如 NSInteger
, CGFloat
等),但不是对象类型。
而且,记住,当你完成对僵尸的测试后,请关闭该诊断功能。