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