변수 배열을 탐색 할 때 배열의 요소를 삭제하지 않는 것이 가장 좋습니다.
삭제 작업으로 인해 어레이 용량이 변경되어 어레이 범위를 벗어난 것과 같은 문제가 발생할 수 있기 때문입니다.
이전에는 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)