迭代时是否可以从mutablearray中删除字典?

for (int i = 0; i< [optionDataArr count]; i++) { NSString *sName = [[optionDataArr objectAtIndex:i] objectForKey:kOptionName]; NSString *sPrice = [[optionDataArr objectAtIndex:i] objectForKey:kOptionExtraPrice]; if (sName.length == 0 && sPrice.length == 0) { [optionDataArr removeObjectAtIndex:i]; } } 

假设optionDataArr包含一个没有值的字典,当上面的代码执行时,我收到:

 Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array' 

使用普通的旧for循环时,可以删除项目,使用快速枚举时不能。

但是,你的代码是越野车。 当你删除第n个元素时,下一个元素将是(n + 2)th。 您需要手动将索引减1以考虑切换的元素。

另外请记住,在这种情况下,您确实需要在循环中对数组长度进行“实时”边界检查,而不是仅使用一个包含长度的临时variables(或者您也需要减less该长度)。

在这条线下面:

 [optionDataArr removeObjectAtIndex:i]; 

添加这一行:

 i--; 

所以,代码将是:

 if (sName.length == 0 && sPrice.length == 0) { [optionDataArr removeObjectAtIndex:i]; i--; } 

原因:在迭代时从数组中删除项目时,索引会更改。 所以,这就是为什么你需要手动递减索引。

Eiko的答案是正确的,但我想显示其他版本使用快速枚举。 您不能使用快速枚举删除项目,因此您必须存储索引,然后再删除相应的项目:

 NSMutableIndexSet * indexesToRemove = [NSMutableIndexSet indexSet]; [optionDataArr enumerateObjectsUsingBlock:^(NSDictionary *dico, NSUInteger idx, BOOL *stop) { if ([dico count] == 0) [indexesToRemove addIndex:idx]; }]; [optionDataArr removeObjectsAtIndexes:indexesToRemove]; 

编辑:

由于Martin R拥塞,你也可以使用indexesOfObjectsPassingTest方法:

 NSIndexSet * indexesToRemove = [optionDataArr indexesOfObjectsPassingTest:^BOOL(NSDictionary *dico, NSUInteger idx, BOOL *stop) { return ([dico count] == 0); }]; [optionDataArr removeObjectsAtIndexes:indexesToRemove]; 

只要你进行Eiko已经提到的修改,你当然可以使用循环的标准。

然而,在Objective C中处理这个问题的方法是迭代数组的一个副本:

 for (id obj in [optionDataArr copy]) { // some processing code if (condition) { [optionDataArr removeObject:obj] } } 

虽然这确实需要数组的副本,除非您确定知道您正在处理大量数据,但我会从可读版本开始,并在必要时优化为plain for循环。