Ios NSMutableArray突变崩溃

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

在dispatch\u异步方法中,我面临“集合在枚举时发生了变化”崩溃。代码如下:

- (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:
在内部使用枚举进行线性搜索。因此,一个块位于包容对象:另一个执行<代码> AddoOb:< /Cord>。代码> NSMutableArray < /代码> s,与其他基础可变对象一样,不能保证是线程安全的。
至少您希望使用
调度队列\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])