配列をトラバースして、配列内の複数の要素を削除します

変数配列をトラバースするときは、配列内の要素を削除しないことをお勧めします。
削除操作により配列容量が変更され、配列が範囲外になるなどの問題が発生する可能性があるためです。
以前、forループトラバーサルを使用しているときにこの問題が発生しました。
当時はenumerateObjectsUsingBlock:を使用するのが慣例でしたが、今回もこの問題が発生したときに、enumerateObjectsUsingBlock:をテストしました。
実験結果は以下のとおりです。

NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];
[array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([obj isEqualToString:@"3"]) {
        [array removeObject:obj];
    }
}];
NSLog(@"%@",array);

// 输出结果:(1,2,4,5)

結果は正常です。

用途:

NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];
for (NSString *obj in array) {
    if ([obj isEqualToString:@"3"]) {
        [array removeObject:obj];
    }
}
NSLog(@"%@",array);

結果はクラッシュです。情報は次のとおりです。

2016-11-11 22:48:06.886 Solutions[15297:2231002] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x1001060b0> was mutated while being enumerated.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff929c14f2 __exceptionPreprocess + 178
    1   libobjc.A.dylib                     0x00007fff8fcb2f7e objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff92a2815c __NSFastEnumerationMutationHandler + 300
    3   Solutions                           0x0000000100000d1c main + 508
    4   libdyld.dylib                       0x00007fff90cd05ad start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

のために使用します:

NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];
for (int i = 0; i < array.count; i++) {
    NSString *obj = array[i];
    if ([obj isEqualToString:@"3"]) {
        [array removeObject:obj];
    }
}
NSLog(@"%@",array);
// 输出结果是:(1,2,4,5)

結果は正常です。Appleが通常のforループの内部処理を修正した可能性があります。以前は、このように書き込むとエラーが発生していました。

実際、最も正確で安全な解決策は、配列を逆の順序でトラバースしてから、要素を削除することです。

たとえば、for inの逆走査:

NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];
for (NSString *obj in array.reverseObjectEnumerator) {
    if ([obj isEqualToString:@"3"]) {
        [array removeObject:obj];
    }
}
NSLog(@"%@",array);
// 输出结果:(1,2,4,5)

使用する

NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];
[array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj isEqualToString:@"3"]) {
                [array removeObject:obj];
            }
        }];

NSLog(@"%@",array);
// 输出结果:(1,2,4,5)

forの逆順

NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];
for (int i = array.count - 1; i >= 0; i--) {
    NSString *obj = array[i];
    if ([obj isEqualToString:@"3"]) {
        [array removeObject:obj];
    }
}
NSLog(@"%@",array);
// 输出结果:(1,2,4,5)

おすすめ

転載: blog.csdn.net/woruosuifenglang/article/details/78466557