Ios NSMutableArray突变崩溃
在dispatch\u异步方法中,我面临“集合在枚举时发生了变化”崩溃。代码如下:Ios NSMutableArray突变崩溃,ios,objective-c,nsmutablearray,grand-central-dispatch,Ios,Objective C,Nsmutablearray,Grand Central Dispatch,在dispatch\u异步方法中,我面临“集合在枚举时发生了变化”崩溃。代码如下: - (void) addCutObjectFromObject: (Object *) object { dispatch_async(self.objectsQueue, ^{ ObjectCut *objectCut = [[[ObjectCut alloc] init] autorelease]; objectCut.objectId = object.uid; objectCut
- (void) addCutObjectFromObject: (Object *) object {
dispatch_async(self.objectsQueue, ^{
ObjectCut *objectCut = [[[ObjectCut alloc] init] autorelease];
objectCut.objectId = object.uid;
objectCut.objectName = object.internal.name;
@synchronized(self.shownChannelsArray) {
if (![self.objectsArray containsObject: objectCut])
{
[self.objectsArray addObject: objectCut];
}
}
});
}
Dispatch_队列是在init方法中创建的,如下所示:
_objectsQueue = dispatch_queue_create("objectsQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_retain(_objectsQueue);
代码在没有同步块的情况下崩溃。据我所知,它不应该崩溃,因为没有循环,应该一个接一个地添加块,等待它们的队列。有人能解释一下为什么会发生这种情况吗?您不是在循环或枚举中调用addCutObjectFromObject:?
如果是,您可能需要检查此部件。错误说明了崩溃的原因。枚举时不允许更改数组
if (![self.objectsArray containsObject: objectCut])
{
[self.objectsArray addObject: objectCut];
}
在上面的代码中,您正在枚举数组并插入一个对象。这就是将给出错误的地方。希望这有帮助:) 啊,这是个棘手的问题。。据我所知(我可能有点不对劲,所以其他人可以随时跟进,但这个可怜的家伙还没有任何回应.) 因此,当执行此操作时,异步块不会立即运行。它将首先被调度,我会想象您多次调用此
addCutObjectFromObject
方法。例如,您调用此方法5次。现在考虑线程。第一次调用被调度,最终开始运行,而le第二个调用被安排,最终开始运行,等等。这就是问题开始的地方,我相信你的罪魁祸首是containsObject
和addObject
。在后台,containsObject正在数组中迭代。由于有多个线程正在执行,而一个线程正在迭代数组,因此可能正在调用addObject
。从而生成“集合在迭代时发生了变化”的崩溃
解决方案的两个选项1) 在containsObject中,检查数组的副本而不是数组本身(这是一种不好的方法,因为它需要复制数组的内容,但很容易放入,对于较小的数组大小,可能是一种快速修复方法) 同样,这应该可以阻止偶尔的崩溃,但这是一个糟糕的解决方案(因为内存重复)
2) 创建一个临时数组以将对象添加到其中,并且在所有线程完成后,将临时数组的内容添加到
self.objectsArray
调度队列\u创建(“objectsquee”,调度队列\u并发)
创建一个并发队列。调度到该队列的任意多个块可以同时执行。很可能containsObject:
在内部使用枚举进行线性搜索。因此,一个块位于至少您希望使用
调度队列\u序列
。除非顺序对您非常重要,或者您的对象没有实现散列
,相等:
,等等,您可能还应该只使用一个集合,而不是手动用数组重新创建一个集合。什么是self.objectsque
?请发布您是如何创建self.objectsque
dispatch\u asynch意味着对象是异步添加的,因此一次可以添加多个对象…还有谁可能正在访问objectsArray
?如果您在没有适当考虑的情况下抛出块,则很可能一个队列发生变异,而另一个队列进行迭代。另外,块添加到队列后的调度方式取决于队列类型:Himanshu和sbarrow可能试图确保您创建的是串行队列,而不是并发队列。@Tommy yip认为这就是问题所在。Polina您需要将DISPATCH_QUEUE_CONCURRENT更改为DISPATCH_QUEUE_SERIALIt,这样任何时候都会崩溃。它不在循环中,只是偶尔会崩溃。是的,可能是这样,但不。无论如何,谢谢你的回答。
if (![self.objectsArray containsObject: objectCut]) =>
if (![[NSArray arrayWithArray:self.objectsArray] containsObject: objectCut])