【发布时间】:2012-12-06 06:18:17
【问题描述】:
我遇到了一个让我完全难过的问题。我会用一个代码示例来说明:
@interface Crasher ()
@property (nonatomic, strong) NSArray *array;
@end
@implementation Crasher
- (void)crash;
{
NSMutableArray *mutable = [NSMutableArray array];
NSArray *items = @[@0, @1, @2, @3];
if ([@YES boolValue])
{
[items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[mutable addObject:obj];
}];
}
else
{
[items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[mutable addObject:obj];
}];
}
[self setArray:mutable];
}
@end
当启用 ARC 并在设备上运行时,上述代码会在 [self setArray:mutable] 行崩溃。该代码永远不会在模拟器上崩溃,也不会在禁用 ARC 的设备上崩溃。使用NSZombieEnabled 表示setter 试图保留一个已经释放的数组。
如果第二个 [mutable addObject:obj] 调用被注释掉,它不会崩溃(但这段代码从一开始就不会执行)。
我已将演示此崩溃的项目上传到 Github 到 aidansteele/arc-crash。我正在使用 Xcode 4.5.2。它似乎不会出现在 Xcode 4.6 上,但这仍在开发人员预览中。我做错了什么?
解决this 答案(在问题中以便我有更多空间),我认为问题不在于-[NSArray enumerateObjectsUsingBlock:],因为如果我更改该方法调用以使用以下@987654329,问题仍然存在@调用。
@interface NSArray (Functional)
- (void)each:(void (^)(id obj))action;
@end
@implementation NSArray (Functional)
- (void)each:(void (^)(id))action;
{
for (NSUInteger idx = 0; idx < [self count]; idx++)
{
action([self objectAtIndex:idx]);
}
}
@end
【问题讨论】:
-
崩溃发生在哪一行?
-
可能是块的问题。如果您使用 ARC,但在前台线程而不是后台线程上进行枚举,会发生什么情况?在枚举完成之前,您可能不想调用 setArray。现在它几乎立即发生。我敢打赌,如果你让 items 数组足够大,它会在模拟器中崩溃。
-
@sergio 我已经编辑了问题以澄清设置属性时会发生这种情况。
-
如果您发现 Xcode 4.5.2 到 4.6 的代码行为有所不同,那么您很可能是在查看 Xcode 错误。请归档。
-
也适用于
NSMutableArray *mutable = [@[] mutableCopy];或任何其他传统上增加保留计数的方法。
标签: objective-c ios memory-management automatic-ref-counting