我遇到了一个让我完全难过的问题。我将用一个代码示例进行说明:
@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
[self setArray:mutable]
启用 ARC 并在设备上运行时,上述代码在线崩溃。该代码永远不会在模拟器上崩溃,也不会在禁用 ARC 的设备上崩溃。UsingNSZombieEnabled
表示 setter 试图保留一个已经释放的数组。
[mutable addObject:obj]
如果第二次调用被注释掉,它不会崩溃(但这段代码从不首先执行)。
我已将演示此崩溃的项目上传到 Github 到aidansteele/arc-crash
. 我正在使用 Xcode 4.5.2。它似乎不会出现在 Xcode 4.6 上,但仍处于开发者预览版中。我究竟做错了什么?
解决这个答案(在问题中以便我有更多空间),我不认为问题出在问题之内-[NSArray enumerateObjectsUsingBlock:]
,因为如果我更改该方法调用以使用以下-[NSArray(Functional) each:]
调用,问题仍然存在。
@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