收集在目标C中被枚举错误时发生变异

NSC*_*Cry 6 objective-c nsmutablearray

以下是我的代码.

NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:@"5"];
[arr addObject:@"7"];
[arr addObject:@"8"];
[arr enumerateObjectsUsingBlock:^(NSString *obj,NSUInteger idx,BOOL *stop) {
        [arr replaceObjectAtIndex:idx withObject:@"10"];
}];
Run Code Online (Sandbox Code Playgroud)

我得到的异常日志

 *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x742a580> was mutated while being enumerated.'
*** First throw call stack:
(0x1596012 0x12a3e7e 0x161ecc5 0x158fe1b 0x158fa16 0x158f925 0x2ba4 0x1e87b7 0x1e8da7 0x1e9fab 0x1fb315 0x1fc24b 0x1edcf8 0x25f8df9 0x25f8ad0 0x150bbf5 0x150b962 0x153cbb6 0x153bf44 0x153be1b 0x1e97da 0x1eb65c 0x29fd 0x2925)
libc++abi.dylib: terminate called throwing an exception
Run Code Online (Sandbox Code Playgroud)

当我使用for循环时,代码工作正常

for (int i = 0 ; i<  arr.count; i++) {
    [arr replaceObjectAtIndex:i withObject:@"8"];
}
Run Code Online (Sandbox Code Playgroud)

所以当我使用enumerateObjectsUsingBlock时,我得到了异常.但两者都是枚举.对 ?那么为什么上层代码会给出was mutated while being enumerated异常?

小智 12

因为你的逻辑是有缺陷的.在枚举期间不允许改变集合.在后一种情况下,NSMutableArray不知道你试图计算它,只是在第一种情况下.然后它抱怨,因为这是一个语义错误.您通常应该通过可变复制数组并改变副本来解决这些问题,然后用更新的副本替换原始数据.


Ram*_*uri 7

你不能这样做:

[arr enumerateObjectsUsingBlock:^(NSString *obj,NSUInteger idx,BOOL *stop) {
        [arr replaceObjectAtIndex:idx withObject:@"10"];
}];
Run Code Online (Sandbox Code Playgroud)

因为在枚举时不能改变集合.

我的建议是将所有操作放在一个操作队列中,并在枚举后执行它们:

NSOperationQueue* queue= [NSOperationQueue new];
queue.maxConcurrentOperationCount=1;
[queue setSuspended: YES];
[arr enumerateObjectsUsingBlock:^(NSString *obj,NSUInteger idx,BOOL *stop) 
{
        NSBlockOperation* op=[NSBlockOperation blockOperationWithBlock: ^ (void)
        {
            [arr replaceObjectAtIndex:idx withObject:@"10"];
        }];     
        [queue addOperation: op];
}];
[queue setSuspended: NO];
[queue waitUntilAllOperationsAreFinished];
Run Code Online (Sandbox Code Playgroud)

另一种方法只是成为另一个集合中的所有项目,并在以后删除它们.写起来也会更简单.