我们在遍历可变数组时,最好不要做删除数组中元素的操作。

因为删除操作可能会引起数组容量的变化,导致数组越界等问题。

以前在使用for循环遍历的时候遇到过这个问题。

当时的做法是使用enumerateObjectsUsingBlock: ,但是这次又遇到这个问题时,顺便好好的测试了一下 forfor inenumerateObjectsUsingBlock:

实验结果如下:

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)

结果正常。

使用for in :

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

使用for :

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)

结果正常,可能是苹果对普通的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)

以前做Java 开发的时候,也遇到过这种遍历删除元素的,那时候的做法是在遍历,删除元素后做一次i–操作。

现在想来,也可以逆序遍历然后直接删除即可。

iOS遍历数组的同时删除元素的更多相关文章

  1. 遍历List过程中删除元素的正确做法(转)

    遍历List过程中删除元素的正确做法   public class ListRemoveTest {     3 public static void main(String[] args) { 4 ...

  2. 【Java】集合(List、Set)遍历、判断、删除元素时的小陷阱

    开发中,常有场景:遍历集合,依次判断是否符合条件,如符合条件则删除当前元素. 不知不觉中,有些陷阱,不知你有没有犯. 一.漏网之鱼-for循环递增下标方式遍历集合,并删除元素 如果你用for循环递增下 ...

  3. (转载)php数组添加、删除元素的方法

    (转载)http://www.phpgs.com/html/php/phpjichu/20120130440.html 带来一篇php 数组 添加元素.删除元素的方法的文章,有需要的php学习者参考下 ...

  4. python同时遍历数组的索引和元素

    1.一般要同时遍历数组的索引和元素需要先确定数组的长度length(元素个数),然后使用range函数来生成数组的索引,最后使用该索引来访问数组的元素. 具体做法如下: l = [2,7,11,15] ...

  5. 以forin的方式遍历数组时进行删除操作的注意点

    今天在修改某项需求的时候,需要在遍历的时候将匹配项移除掉,采用的时forin的方式遍历,然后运行的时候却crash掉了 for (NSString*str in self.btnArray) { if ...

  6. php 数组 添加元素、删除元素

    拆分数组 PHP数组添加一个元素的方式: push(), arr[], Php代码 $arr = array(); array_push($arr, el1, el2 ... eln); 但其实有一种 ...

  7. js数组依据下标删除元素

    最近在项目中遇到了一些问题,基础性的东西记得不牢固,就总结一下放在这里备再次查找,对操作js数组的一些问题一些常用的记录! 1.创建数组 var array = new Array(); var ar ...

  8. 遍历List、Map删除元素

    遍历List删除元素 方法一: List<String> list = new ArrayList<>(); list.add("1"); list.add ...

  9. js数组添加或删除元素

    var arr = new Array(); arr[] = "aaa"; arr[] = "bbb"; arr[] = "ccc"; ar ...

随机推荐

  1. 【django小练习之主机管理界面】

    需求: 利用django,js,bootstrap等实现登录,主机管理等操作. 实现截图 登录界面 主机界面,添加及编辑 部门管理界面 代码实现 目录层级 settings.py "&quo ...

  2. [SDOI 2016]征途

    Description 题库链接 将一个长度为 \(n\) 的正整数序列分为 \(m\) 段,问你这 \(m\) 段最小的方差 \(v\) 为多少.输出 \(v\times m^2\) . \(1\l ...

  3. [JSOI2008]球形空间产生器

    Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球 面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧 ...

  4. 【Noip2017游记】

    好像是考Noip的第5个年头了...高中的第一次Noip... 考了三年PJ,今年是第二次TG,希望不要像去年那么萎(gou) Day -1 考前停课了挺久的来着的,学长出了N套题来模拟,自己练了DP ...

  5. Codeforces 812E Sagheer and Apple Tree

    大致题意: 给你一颗树,这个树有下列特征:每个节点上有若干个苹果,且从根节点到任意叶子节点的路径长度奇偶性相同. 甲和乙玩(闲)游(得)戏(慌). 游戏过程中,甲乙轮流将任意一个节点的若干个苹果移向它 ...

  6. [Codeforces]852I - Dating

    题目大意:给定一棵n个点的树,每个点上有一个汉子或妹子,每人有一个权值,每次询问一条链上选出一对权值相等的男女有多少种选法.(n,q<=10^5) 做法:比较显然的树上莫队,熟悉序列莫队那套理论 ...

  7. 51 nod 1766 树上的最远点对(线段树+lca)

    1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题   n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个 ...

  8. [BZOJ]1031 字符加密Cipher(JSOI2007)

    持续划水中…… 感觉BZOJ上AC人数多的基本都是一些模板题,也就是某些算法的裸题.这些题目mark一下到时候回来复习也是不错的选择. Description 喜欢钻研问题的JS同学,最近又迷上了对加 ...

  9. [ Java学习基础 ] Java构造函数

    构造方法是类中特殊方法,用来初始化类的实例变量,它在创建对象(new运算符)之后自动调用. Java构造方法的特点如下: 构造方法名必须与类名相同. 构造方法没有任何返回值,包括void. 构造方法只 ...

  10. Atom 编辑器安装 linter-eslint 插件,并配置使其支持 vue 文件中的 js 格式校验

    安装方式有如下几种. 1.最常用的安装方式. # 进入atom插件文件夹 cd ~/.atom/packages/ # git clone 插件源文件 git clone https://github ...