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

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

以前在使用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. Spark RDDs vs DataFrames vs SparkSQL

    简介 Spark的 RDD.DataFrame 和 SparkSQL的性能比较. 2方面的比较 单条记录的随机查找 aggregation聚合并且sorting后输出 使用以下Spark的三种方式来解 ...

  2. Linux OpenGL 实践篇-5 纹理

    纹理 在之前的实践中,我们所渲染的物体的表面颜色都是纯色或者根据顶点位置计算出的一个颜色,这种方式在表现物体细节方面是比较吃资源的,因为我们每增加一个细节,我们就需要定义更多的顶点及其属性.所以美术人 ...

  3. MyBatis 与 Spring 整合

    MyBatis-Spring 项目 目前大部分的 Java 互联网项目,都是用 Spring MVC + Spring + MyBatis 搭建平台的. 使用 Spring IoC 可以有效的管理各类 ...

  4. laravel整合JWT遇到的问题及解决方案

    1.在执行 php artisan jwt:secret 生成密钥的时候,报错Method Tymon\JWTAuth\Commands\JWTGenerateCommand::handle() do ...

  5. Kylin系列之二:原理介绍

    Kylin系列之二:原理介绍 2018年4月15日 15:52 因何而生 Kylin和hive的区别 1. hive主要是离线分析平台,适用于已经有成熟的报表体系,每天只要定时运行即可. 2. Kyl ...

  6. Hibernate | Spring JPA | MySQL 使用过程遇到的一些问题

    1. 使用过程 2. 背景 3. 遇到问题 3.1 不指定Hibernate数据库方言,默认SQL生成方式 3.2 抛出异常Hibernate加入了@Transactional事务不会回滚 3.3 H ...

  7. 阅读DSSS.py 并修改成支持python3.6

    项目地址:https://github.com/stamparm/DSSS 功能:一款小型注入工具 代码如下URL:https://github.com/stamparm/DSSS/blob/mast ...

  8. python 网路爬虫(二) 爬取淘宝里的手机报价并以价格排序

    今天要写的是之前写过的一个程序,然后把它整理下,巩固下知识点,并对之前的代码进行一些改进. 今天要爬取的是淘宝里的关于手机的报价的信息,并按照自己想要价格来筛选. 要是有什么问题希望大佬能指出我的错误 ...

  9. [HNOI2009]图的同构

    Description 求两两互不同构的含n个点的简单图有多少种. 简单图是关联一对顶点的无向边不多于一条的不含自环的图. a图与b图被认为是同构的是指a图的顶点经过一定的重新标号以后,a图的顶点集和 ...

  10. Go学习——go+channel实战(转)

    转载:http://studygolang.com/articles/2423 背景 在最近开发的项目中,后端需要编写许多提供HTTP接口的API,另外技术选型相对宽松,因此选择Golang + Be ...