安全地执行对 NSMutableArray 的更改

Safely perform changes to NSMutableArray

什么会导致 NSMutableArray 的分配或更改崩溃? 我有一个包含自定义对象的可变数组,并且我始终只保留其中的 3 个最新对象,其余的都被删除。我开始打电话

[myArray insertObject:newObject atIndex:0];

if (myArray.count > 3)
    [myArray removeLastObject]; // Crash

但是每当我这样做太快时,最后一行会导致无异常崩溃。 我知道在枚举数组时不允许添加或删除数组的对象,但我不会在任何地方枚举 myArray 除非对其调用 count 执行隐式枚举。我也试过这样做:

NSMutableArray *tmp = [myArray mutableCopy];
[tmp removeLastObject];
myArray = tmp; // Crash

但同样的事情发生了,它在最后一行崩溃了。同样,这在缓慢进行时效果很好。当用户点击按钮时会调用操作本身,如果点击得太快,每次都会崩溃。

编辑:

我应该补充一点,所有这些都在运行 UICollectionViewcellForItemAtIndexPath 方法中。

我能想到崩溃的两个可能原因:

1) 数组正在 accessed/mutated 来自多个线程 2) 数组中的某个对象在某处被过度释放,导致它在数组中仍然存在时被释放。

简短回答:尝试在 Instruments 和 select "Zombies" instrument 中分析您的应用程序。当崩溃发生时,您可能会收到僵尸警报,在这种情况下,您可以获得导致您的内存被踩踏的所有事情的积压日志。

首先,请 post 崩溃消息。很高兴知道您实际看到的是什么错误。


我想知道如果你切换到不可变数组会发生什么。将 myArray 切换为 NSArray * 并使用以下内容。

myArray = [self updatedArray:myArray withObject:newObject];

其中 -updatedArray:withObject:

- (NSArray *)updatedArray:(NSArray *)array withObject:(id)object {
    switch (array.count) {
    case 0: return @[object];
    case 1: return @[object, array[0]];
    default: return @[object, array[0], array[1]];
    }
}

或更适合测试

NSArray *temp = [self updatedArray:myArray withObject:newObject];
myArray = temp; // I assume the crash will be here!

如果代码在我的评论处崩溃,那么解除分配 myArray 就是导致崩溃的原因。我的猜测是数组中的一项指向错误的内存(僵尸或类似的东西)。

我认为根本原因是这个变量同时被多个线程访问。

访问数组时可以使用这个

@synchronized(self) {
    //Your accessed code here
}