iOS可变数组在遍历过程中如何删除元素?

在之前的面试中,面试官问我一个项目中的问题:在可变数组的遍历过程中,删除其中的元素,会发生什么问题?

我们都知道,在数组的遍历过程中,不要删除数组中的元素,会引起crash,可是今天发现并不是所有的循环方式都会造成crash。

下面,我们写一段代码进行测试:

//我们有一个可变数组
NSMutableArray *mArr = [NSMutableArray arrayWithObjects:@1, @2, @3, @4, @5, @6, nil];

// 普通的循环遍历方式
for (NSUInteger i = 0; i < mArr.count; i++) {
   [mArr removeObjectAtIndex:i];
}
NSLog(@"%@", mArr);
//打印结果为:2, 4, 6,而且程序没有crash

// 使用迭代器遍历
[mArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
   [mArr removeObject:obj];
}];
NSLog(@"%@", mArr);
//打印结果为:2, 4, 6,而且程序没有crash

// 使用for-in遍历
for (NSNumber *obj in mArr) {
   [mArr removeObject:obj];
}
NSLog(@"%@", mArr);
// 程序crash,
// Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x6000002588d0> was mutated while being enumerated.'

所以在可变数组的遍历过程中,根据不同的遍历方式,会产生不同的问题。

那么,如果想在遍历过程中,删除数组的元素,该怎么处理呢

大众的做法是新建一个可变数组,把要想保留的元素,加入到新的数组,方法是可行的,有没有更好的解决方案呢?

答案是有的。采用逆序遍历

// 逆序遍历
[mArr enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
   [mArr removeObject:obj];
}];

// 逆序遍历
for (NSNumber *obj in [mArr reverseObjectEnumerator]) {
   [mArr removeObject:obj];
}

这样,程序就不会crash,数组中的元素也成功移除了。

补充
在实际开发中,笔者建议要谨慎使用,要多加测试,笔者在使用分割字符串后,初始化一个可变数组进行删除操作就crash了。

你可能感兴趣的:(iOS可变数组在遍历过程中如何删除元素?)