迭代数组或字典并删除条目的安全方法?

时间:2010-05-07 10:06:32

标签: iphone objective-c cocoa cocoa-touch core-foundation

我听说做这样的事情是个坏主意。但我确信有一些经验法则可以帮助你做到这一点。

当我遍历NSMutableDictionary或NSMutableArray时,我经常需要删除条目。典型案例:您迭代它,并将条目与某些内容进行比较。有时结果是“不再需要”,你必须删除它。但这样做会影响所有行的索引,不是吗?

那么我怎样才能安全地迭代它而不会意外地超出界限或跳过尚未检查过的元素?

5 个答案:

答案 0 :(得分:8)

您可以通过创建临时数组或字典来实现。任

  • (字典)稍后将要删除的密钥添加到临时数组或
  • (数组)稍后将要删除的索引添加到NSIndexSet
  • 将您想要保持的对象添加到临时数组或字典

然后迭代临时TODELETE列表,从主列表中删除(可能有实用方法),或者将现有的dictonary / array替换为“临时”列表。

答案 1 :(得分:4)

如果在枚举同一个数组时从可变数组中删除对象,则会使应用程序崩溃。跟踪要删除的对象(可以将其索引保存在NSIndexSet中)并在枚举循环之外使用方法-(void)removeObjectsAtIndexes:(NSIndexSet *)indexes。或者,保留您要枚举的NSArray个对象,并在完成循环后使用-(void)removeObjectsInArray:(NSArray *)otherArray删除它们。

检查NSMutableArray文档以获取有关方法的说明。

http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

答案 2 :(得分:2)

或者您始终可以在循环中使用显式索引,然后在删除对象时对其进行操作。所以它看起来像这样

for(unsigned int i = 0; i < [myArray count]; i++) {
      id obj = [myArray objectAtIndex:i];
      if (condition) {
           [myArray removeObject: obj];
           i--;
      }
}

答案 3 :(得分:1)

这是创建复制,迭代和删除的一种聪明方法:

for (id obj in [[myArray copy] autorelease]) {
    BOOL condition = ...
    if (condition) {
        [myArray removeObject:obj];
    }
}

如果由于某种原因你反向迭代很重要:

for (id obj in [[[myArray copy] autorelease] reverseObjectEnumerator]) {
    BOOL condition = ...
    if (condition) {
        [myArray removeObject:obj];
    }
}

答案 4 :(得分:1)

鉴于您的数组不包含任何[NSNull null]元素(它们很可能无论如何都不会),您可以在枚举期间简单地替换您需要使用[NSNull null]删除的所有项目,并且一旦完成枚举只需调用[array removeObjectIdenticalTo:[NSNull null]][NSNull null]是一个单例和框架黑客,允许将nil插入数组中。)

当内存出现问题时,这可能很方便,因此数组副本不是一个选项,或者当数组不能被副本替换时。