原文网址: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控制跳出枚举器.
}
}];

 
 

第二种方法,利用变量, 你的意思是遍历的是 tmp 操作的是 arr 对吧.我有个疑问就是在操作完 arr 之后赋值给 tmp 这个不会造成 was mutated while being enumerate 这个错误么?

 

楼主,建议你应该写详细点,方法二补充下:
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。

遇到一个问题,跟踪了半天才发现原因。(现象是,客户老是说在下载的过程中,过一会就出现崩溃的现象, 只要点了下载按钮, 不做任何操作, 然后期刊就开始正常下载了,过大概5分钟后,再去看,程序就已经崩溃了)
在做《时装传媒》ipad应用时,首页的下载页面,下载时,会不断地去更新页面上的下载进度,同时还有一个15秒的timer, 会每15秒切换当前显示的是男装,女装或者艺术刊页面。这个timer会把当前的scrollView中显示的封面图片进行移除,然后再替换,以实现自动更换首页封面的功能
 
崩溃时提示:
Collection <UIButtonContent: 0x2341234> was mutated while being enumerated
(在网上搜了一下,发现有一个类似的问题:'NSGenericException', reason: '*** Collection <__NSArrayM: 0x8ef350> was mutated while being enumerated.')

根据这个提示, 想了一下,觉得应该在做遍历的过程中,修改了这个NSArray或者是NSMutableArray。后来想想, 这可能是多线程并发访问时出现的问题, 沿崩溃时的堆栈找了一下,果然找到。

因为我们在下载时, 使用了Block每当接受到数据,就去更新一下一个UIScrollView中的下载进度条的百分比。

而另有一个NSTimer, 会隔一段时间把这个UIScrollView中的全部元素清空,然后再重新添加, 因为可能有动态的元素需要添加或者删除。

运行时, 就会出现,两个线程同时去访问的情况, 当Block正在去更新UIScrollView中的这个元素时, NSTimer中可能正在执行清除操作,所以就崩了。

原来,在同一时间,不同的线程同时读取和修改了NSMutaleArray。

解决办法:避免多线程同时去修改一个对象, 避免做遍历时,这个对象被修改,根据这个思想,可以考虑加锁,或者直接使用atomic的方式来做。

 

【转】was mutated while being enumerated 你是不是以为你真的懂For...in... ??的更多相关文章

  1. iOS之解决崩溃Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.

    崩溃提示:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CAL ...

  2. 异常Crash之 NSGenericException,NSArray was mutated while being enumerated

    *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NS ...

  3. Objective-C Collection was mutated while being enumerated crash

    Collection was mutated while being enumerated

  4. *** Collection <__NSArrayM: 0x600000647380> was mutated while being enumerated.

    *** Collection <__NSArrayM: 0x600000647380> was mutated while being enumerated.

  5. bug:*** Collection <__NSArrayM: 0x1c444d440> was mutated while being enumerated.

    崩溃提示:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CAL ...

  6. 解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.-

    bug: 今天做项目的时候遇到了这样一个崩溃信息: 解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumera ...

  7. reason: '*** Collection <__NSCFArray: 0x7ffa43528f70> was mutated while being enumerated.'

    一,错误分析 1.崩溃代码如下: //遍历当前数组,判断是否有相同的元素 for (NSString *str in self.searchHistoryArrM) { if ([str isEqua ...

  8. 解决Collection <__NSArrayM: 0x7f8168f7a750> was mutated while being enumerated.'

    当程序出现这个提示的时候,是因为你一边便利数组,又同时修改这个数组里面的内容,导致崩溃,网上的方法如下: NSMutableArray * arrayTemp = xxx; NSArray * arr ...

  9. 第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash

    1. UIImage imageWithContentsOfFile卡顿 [[UIImage alloc] initWithContentsOfFile 卡顿 2.uitableview scroll ...

随机推荐

  1. 九度OJ 1528 最长回文子串 -- Manacher算法

    题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...

  2. OpenJudge 2802 小游戏 / Poj 1101 The Game

    1.链接地址: http://bailian.openjudge.cn/practice/2802 http://poj.org/problem?id=1101 2.题目: 总时间限制: 1000ms ...

  3. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...

  4. 快速排序算法 Quick sort

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046189.html 首先随机选择一个轴,并调整数组内各个数字,使得比轴值大的数在轴的右边, ...

  5. Mac 系统下安装 MySql

    Mac原生没有带MySql,想要使用需要自己去安装. 下载. 首先去mysql官网下载安装包. 由于现在mysql对企业有服务,所以有所谓社区版(community)和企业版(enterprise), ...

  6. fuser 命令概述

    fuser 概述 fuser命令是用来显示所有正在使用着指定的file, file system 或者 sockets的进程信息. 例一: #fuser –m –u /mnt/usb1 /mnt/us ...

  7. IE专用CSS,最全的CSS hack方式一览

    http://blog.csdn.net/freshlover/article/details/12132801

  8. matlab2014在mac Yosemite下出现java空指针情况

    恢复方法为 使用xcode打开 /System/Library/CoreServices/SystemVersion.plist 将 ProductVersion 下的10.10或10.10.1改为1 ...

  9. CSS 之 @media

    @media 版本:CSS2 兼容性:IE5+ 语法: @media  sMedia  {sRules} 取值: sMedia : 指定设备名称.请参阅设备类型 all, aural, braille ...

  10. Kinetic使用注意点--blob

    new Blob(config) 参数: config:包含所有配置项的对象. { points: "存放路径点的数组,可以用一层数组[a,b,c,d].二层数组[[a,b],[c,d]]或 ...