NSArray *tempArray = @[@"A",@"A",@"B",@"C",@"D",@"A"];
NSMutableArray *dataArray = [NSMutableArray arrayWithArray:tempArray];
正序遍历
方式一, 使用 for in遍历可变数组的同时删除元素会造成崩溃:
for (NSString *obj in dataArray) {
if ([obj isEqualToString:@"A"]) {
[dataArray removeObject:obj];
}
}
方式二, 使用 enumerateObjectsUsingBlock 遍历可变数组的同时删除元素:
[dataArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"obj ----- %@---index---%ld",obj,idx);
if ([obj isEqualToString:@"A"]) {
[dataArray removeObject:obj];
}
}];
方式三, 使用 for index 方式遍历可变数组同时删除元素:
for (int i = 0; i < dataArray.count; i++) {
NSString *obj = dataArray[i];
NSLog(@"obj -----%@---index---%d",obj,i);
if ([obj isEqualToString:@"A"]) {
[dataArray removeObject:obj];
}
}
结论
从上面来看只for in会造成崩溃,其他方式对数组遍历,然后再删除元素就没有问题了。
但是如果删除元素,数组总长度会变化,如果内部再嵌套循环,那么就无法完全遍历
逆序遍历
方式一, 使用 for in遍历可变数组的同时删除元素仍会造成崩溃:(亲测)
for (NSString *obj in dataArray.reverseObjectEnumerator) {
if ([obj isEqualToString:@"A"]) {
[dataArray removeObject:obj];
}
}
方式二, enumerateObjectsWithOptions:NSEnumerationReverse
[dataArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"obj -----%@---index---%ld",obj,idx);
if ([obj isEqualToString:@"A"]) {
[dataArray removeObject:obj];
}
}];
obj -----A---index---5
obj -----A---index---4
obj -----A---index---3
obj -----D---index---2
obj -----C---index---1
obj -----B---index---0
结论
从上面来看只for in会造成崩溃,enumerateObjectsWithOptions对数组遍历会逆序循环6次,内部元素顺序会发生改变。
总结
1.如果是单循环,那么删除元素,removeObject 会将数组内部相同元素都删除。
2.如果是嵌套循环,那么删除元素,数组长度会发生改变,从而无法完全遍历,建议copy一个数组进行循环删减。也可以使用逆序遍历enumerateObjectsWithOptions:方式