安全地执行对 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
但同样的事情发生了,它在最后一行崩溃了。同样,这在缓慢进行时效果很好。当用户点击按钮时会调用操作本身,如果点击得太快,每次都会崩溃。
编辑:
我应该补充一点,所有这些都在运行 UICollectionView
的 cellForItemAtIndexPath
方法中。
我能想到崩溃的两个可能原因:
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
}
什么会导致 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
但同样的事情发生了,它在最后一行崩溃了。同样,这在缓慢进行时效果很好。当用户点击按钮时会调用操作本身,如果点击得太快,每次都会崩溃。
编辑:
我应该补充一点,所有这些都在运行 UICollectionView
的 cellForItemAtIndexPath
方法中。
我能想到崩溃的两个可能原因:
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
}