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'
答案 0 :(得分:4)
使用普通旧for循环时可以删除项目,使用快速枚举时不能删除。
但是你的代码很麻烦。删除第n个元素时,下一个元素将是(n + 2)th。您需要手动将索引递减1以考虑转移的元素。
还要记住,在这种情况下,你真的需要做&#34;实时&#34;在循环中检查数组长度的边界,而不仅仅是使用保持长度的临时变量(或者你也需要递减那个)。
答案 1 :(得分:3)
在这一行之下:
[optionDataArr removeObjectAtIndex:i];
添加以下行:
i--;
所以,代码是:
if (sName.length == 0 && sPrice.length == 0) {
[optionDataArr removeObjectAtIndex:i];
i--;
}
原因:在迭代数组时从数组中删除项目时,索引会发生更改。所以,这就是你需要手动减少索引的原因。
答案 2 :(得分:3)
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 sugested时,您也可以使用indexesOfObjectsPassingTest
方法:
NSIndexSet * indexesToRemove = [optionDataArr indexesOfObjectsPassingTest:^BOOL(NSDictionary *dico, NSUInteger idx, BOOL *stop) {
return ([dico count] == 0);
}];
[optionDataArr removeObjectsAtIndexes:indexesToRemove];
答案 3 :(得分:1)
如果您进行了Eiko已经提到的修改,您当然可以使用标准for循环。
然而,在Objective C中处理此问题的惯用方法是迭代数组的副本:
for (id obj in [optionDataArr copy]) {
// some processing code
if (condition) {
[optionDataArr removeObject:obj]
}
}
虽然这确实需要数组的副本,除非您确定要处理大量数据,否则我将从可读版本开始,并在必要时优化到plain for循环。