【转】was mutated while being enumerated 你是不是以为你真的懂For...in... ??
原文网址:http://www.jianshu.com/p/ad80d9443a92
支持原创,如需转载, 请注明出处
你是不是以为你真的懂For...in... ??
哈哈哈哈, 我也碰到了这个报错 .
究其原因, 顾名思义 "在枚举的时候发生了变化"
for...in...利用了快速枚举NSFastEnumerate
当我们想要改变数组变量中的数据或者删除数组中的数据的时候,不能用for...in...
应该是Objective-C中的foreach循环与Java中的相似,在内部是用iterator(迭代器)实现遍历的。而不管是在Java还是C++中,一旦修改了被遍历对象,在修改前生成的iterator都会失效,所以《C++ Primer》及Java课本中曾警告过不要在用iterator遍历集合时增删集合元素,看来Objective-C中也是一样。
NSArray的枚举操作中有一条需要注意:对于可变数组进行枚举操作时,你不能通过添加或删除对象这类操作来改变数组容器。如果你这么做了,枚举器会很困惑,而你将得到未定义的结果。
所以我这里给出三种解决方案
1.利用for loop ()
for (int i = 0; i < arr.count; i++) {
if (...) {
// do sth ;
}
}
2.利用临时变量
NSArray *tmp = [NSArray arrayWithArray:arr];
for (id obj in tmp) {
if (...) {
// do sth ;
}
}
3.enumerateObjectsUsingBlock(推荐)
[arr enumerateObjectsUsingBlock:^(NSMutableDictionary *obj, NSUInteger idx, BOOL *stop) {
if (...) {
// do sth
*stop = YES; // 相当于break ; stop控制跳出枚举器.
}
}];
- 爱吃草莓的Rock 2016.04.26 12:34
第二种方法,利用变量, 你的意思是遍历的是 tmp 操作的是 arr 对吧.我有个疑问就是在操作完 arr 之后赋值给 tmp 这个不会造成 was mutated while being enumerate 这个错误么?
3 楼 · 2016.04.26 13:04
楼主,建议你应该写详细点,方法二补充下:
NSMutableArray *duplicateArray = [OriginalArray mutableCopy];
for(id obj in duplicateArray){
if ([ob isEqualToString:@"3"]){
[OriginalArray removeObject:obj];
}
}
*** First throw call stack:
(0x353d088f 0x37777259 0x353d03b3 0x34e576a9 0x34ea914d 0x1252d9 0x16c281 0x16aadb 0x3425f887 0x3425f281 0x3425f911 0x16a931 0x3425dc59 0x34260817 0x3278ddfb 0x3278dcd0)
terminate called throwing an exception
*** First throw call stack:
(0x353d088f 0x37777259 0x353d03b3 0x34e576a9 0x34ea914d 0x1252d9 0x16c281 0x16aadb 0x3425f887 0x3425f281 0x3425f911 0x16a931 0x3425dc59 0x34260817 0x3278ddfb 0x3278dcd0)
terminate called throwing an exception2013-04-08 15:03:06.800 NanGuangTV[45122:707] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x8ef350> was mutated while being enumerated.'
*** First throw call stack:
(0x353d088f 0x37777259 0x353d03b3 0x34e576a9 0x34ea914d 0x1252d9 0x16c281 0x16aadb 0x3425f887 0x3425f281 0x3425f911 0x16a931 0x3425dc59 0x34260817 0x3278ddfb 0x3278dcd0)
terminate called throwing an exception(lldb)
遇到这么个问题。郁闷。
原来是,我用了多线程,分别读取一个NSMutaleArray时报出来的Error!
原来,在同一时间,不同的线程同时读取和修改了NSMutaleArray。
根据这个提示, 想了一下,觉得应该在做遍历的过程中,修改了这个NSArray或者是NSMutableArray。后来想想, 这可能是多线程并发访问时出现的问题, 沿崩溃时的堆栈找了一下,果然找到。
因为我们在下载时, 使用了Block每当接受到数据,就去更新一下一个UIScrollView中的下载进度条的百分比。
而另有一个NSTimer, 会隔一段时间把这个UIScrollView中的全部元素清空,然后再重新添加, 因为可能有动态的元素需要添加或者删除。
运行时, 就会出现,两个线程同时去访问的情况, 当Block正在去更新UIScrollView中的这个元素时, NSTimer中可能正在执行清除操作,所以就崩了。
原来,在同一时间,不同的线程同时读取和修改了NSMutaleArray。
解决办法:避免多线程同时去修改一个对象, 避免做遍历时,这个对象被修改,根据这个思想,可以考虑加锁,或者直接使用atomic的方式来做。
【转】was mutated while being enumerated 你是不是以为你真的懂For...in... ??的更多相关文章
- iOS之解决崩溃Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.
崩溃提示:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CAL ...
- 异常Crash之 NSGenericException,NSArray was mutated while being enumerated
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NS ...
- Objective-C Collection was mutated while being enumerated crash
Collection was mutated while being enumerated
- *** Collection <__NSArrayM: 0x600000647380> was mutated while being enumerated.
*** Collection <__NSArrayM: 0x600000647380> was mutated while being enumerated.
- bug:*** Collection <__NSArrayM: 0x1c444d440> was mutated while being enumerated.
崩溃提示:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CAL ...
- 解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.-
bug: 今天做项目的时候遇到了这样一个崩溃信息: 解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumera ...
- reason: '*** Collection <__NSCFArray: 0x7ffa43528f70> was mutated while being enumerated.'
一,错误分析 1.崩溃代码如下: //遍历当前数组,判断是否有相同的元素 for (NSString *str in self.searchHistoryArrM) { if ([str isEqua ...
- 解决Collection <__NSArrayM: 0x7f8168f7a750> was mutated while being enumerated.'
当程序出现这个提示的时候,是因为你一边便利数组,又同时修改这个数组里面的内容,导致崩溃,网上的方法如下: NSMutableArray * arrayTemp = xxx; NSArray * arr ...
- 第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash
1. UIImage imageWithContentsOfFile卡顿 [[UIImage alloc] initWithContentsOfFile 卡顿 2.uitableview scroll ...
随机推荐
- mysql主配置文件my.cnf详细说明
MySQL配置文件my.cnf 例子最详细翻译,可以保存做笔记用[转载]#BEGIN CONFIG INFO#DESCR: 4GB RAM, 只使用InnoDB, ACID, 少量的连接, 队列负载大 ...
- 不用jsonp实现跨域请求
这几天要用到跨域请求,我在网上找了好多资料,最后自己研究出来一个比较简单方便的, 请求的过程和jquery普通的ajax一样.我用的是.net平台 ,IIS7.5 来看一下后台的代码,我是用MVC的C ...
- mysql 数据库备份,恢复。。。。
mysql 数据备份,恢复,恢复没写,这里只写了备份... 先暂作记录吧! 备份:表结构和数据完全分开,默认有一个文件会记录所有表的结构,然后表中数据的备份 如果超过分卷的大小则会分成多个文件,不然则 ...
- Maven插件实现的autoconfig机制(转)
autoconfig这种机制在软件开发和发布的过程中是非常方便也是非常必要的一种动态替换配置信息的一种手段,一种很贴切的比喻:这个就像在windows下面安装一个软件时,我们按照安装向导给我们弹出提示 ...
- 企业生产环境下不同业务的linux分区建议
常规分区方案: /boot: 100M swap:内存的1至1.5倍 / : 剩余硬盘大小 DB及存储:有大量重要的数据 /boot : 100M swap: 内存的1至1.5倍,如果内存大于等于1 ...
- 转:testlink 环境搭建(傻瓜版)
testlink 环境搭建(傻瓜版) 2011-11-24 22:23 by 虫师, 12322 阅读, 4 评论, 收藏, 编辑 今天抽了点时间把testlink 环境搭建了一下,一直觉得这东西不怎 ...
- Python原型模式
如果想根据现有对象复制出新的对象并对其修改,可以考虑原型模式(Prototype Pattern) class Point: __slots__ = ("x", "y&q ...
- sparkR原理
p.p1 { margin: 0.0px 0.0px 10.0px 0.0px; font: 11.0px "Times New Roman"; min-height: 12.0p ...
- ARM的工作环境和工作模式
工作环境: 可以称之为“数据环境,”数据总线16位或者32位,应用于不同的情况下.16位的情况下,工作速度快,代码密度高. 工作模式: 设置程序数据所处的状态,为移植操作系统提供方便.
- ?Object-C获取手机设备信息
一.获取UiDevice设备信息 // 获取设备名称 NSString *name = [[UIDevice currentDevice] name]; // 获取设备系统名称 NSString *s ...