Iphone 迭代数组或字典并删除条目的安全方法?
我听说这样做是个坏主意。但我相信有一些经验法则可以帮助我们做到这一点 当我在NSMutableDictionary或NSMutableArray上迭代时,经常需要删除条目。典型情况:您对其进行迭代,并将条目与其他内容进行比较。有时结果是“不再需要了”,你必须将其删除。但是这样做会影响所有行的索引,不是吗Iphone 迭代数组或字典并删除条目的安全方法?,iphone,objective-c,cocoa,cocoa-touch,core-foundation,Iphone,Objective C,Cocoa,Cocoa Touch,Core Foundation,我听说这样做是个坏主意。但我相信有一些经验法则可以帮助我们做到这一点 当我在NSMutableDictionary或NSMutableArray上迭代时,经常需要删除条目。典型情况:您对其进行迭代,并将条目与其他内容进行比较。有时结果是“不再需要了”,你必须将其删除。但是这样做会影响所有行的索引,不是吗 那么,我怎样才能安全地迭代它而不意外地超出边界或跳过未检查的元素呢?您可以通过创建临时数组或字典来实现。或者 (字典)将以后要删除的键添加到临时数组或 (数组)将稍后要删除的索引添加到NSIn
那么,我怎样才能安全地迭代它而不意外地超出边界或跳过未检查的元素呢?您可以通过创建临时数组或字典来实现。或者
- (字典)将以后要删除的键添加到临时数组或
- (数组)将稍后要删除的索引添加到
或NSIndexSet
- 将要保留的对象添加到临时数组或字典中
然后迭代临时TODELETE列表,从主列表中删除(可能有实用方法),或者用“临时”数组替换现有的dictorial/array。您可以通过创建临时数组或字典来完成此操作。或者
- (字典)将以后要删除的键添加到临时数组或
- (数组)将稍后要删除的索引添加到
或NSIndexSet
- 将要保留的对象添加到临时数组或字典中
然后迭代临时TODELETE列表,从主列表中删除(可能有实用方法),或者用“临时”数组替换现有的Dictorial/array。如果在枚举同一数组时从可变数组中删除对象,则会使应用程序崩溃。跟踪要删除的对象(可以将其索引保留在
NSIndexSet
中),并在超出枚举循环后使用方法-(void)removeObjectsIndexes:(NSIndexSet*)index
。或者,保留正在枚举的对象的NSArray
,并在完成循环后使用-(void)removeObjectsInArray:(NSArray*)otherArray
删除它们
查看NSMutableArray
文档以了解方法的说明
如果在枚举同一数组时从可变数组中删除对象,将导致应用程序崩溃。跟踪要删除的对象(可以将其索引保留在
NSIndexSet
中),并在超出枚举循环后使用方法-(void)removeObjectsIndexes:(NSIndexSet*)index
。或者,保留正在枚举的对象的NSArray
,并在完成循环后使用-(void)removeObjectsInArray:(NSArray*)otherArray
删除它们
查看NSMutableArray
文档以了解方法的说明
以下是创建副本、迭代和删除的巧妙方法:
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];
}
}
下面是一种创建副本、迭代和删除的巧妙方法:
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];
}
}
或者,您可以始终在循环中使用显式索引,然后在删除对象时对其进行操作。看起来是这样的
for(unsigned int i = 0; i < [myArray count]; i++) {
id obj = [myArray objectAtIndex:i];
if (condition) {
[myArray removeObject: obj];
i--;
}
}
for(无符号整数i=0;i<[myArray count];i++){
id obj=[myArray objectAtIndex:i];
如果(条件){
[myArray removeObject:obj];
我--;
}
}
或者您可以始终在循环中使用显式索引,然后在删除对象时对其进行操作。看起来是这样的
for(unsigned int i = 0; i < [myArray count]; i++) {
id obj = [myArray objectAtIndex:i];
if (condition) {
[myArray removeObject: obj];
i--;
}
}
for(无符号整数i=0;i<[myArray count];i++){
id obj=[myArray objectAtIndex:i];
如果(条件){
[myArray removeObject:obj];
我--;
}
}
鉴于数组不包含任何[NSNull null]
元素(很可能不会),您只需在枚举期间将需要删除的所有项替换为[NSNull null]
,一旦完成枚举,只需调用[array removeObjectiveIdenticalTo:[NSNull]
([NSNull null]
是一种单例和框架黑客,允许将nil插入数组)
当内存存在问题,因此阵列副本不是一个选项,或者阵列无法被副本替换时,这非常方便。鉴于您的阵列不包含任何
[NSNull null]
元素(很可能无论如何都不包含),您只需将需要删除的所有项目替换为[NSNull]
在枚举期间和枚举完成后,只需调用[array RemoveObjectiveIdenticalTo:[NSNull null]]
([NSNull null]
是一种允许将nil插入数组的单例和框架攻击)
如果内存存在问题,因此阵列副本不是一个选项,或者阵列根本无法被副本替换,那么这将非常方便