遇到一個問題,跟蹤了半天才發(fā)現(xiàn)原因。(現(xiàn)象是,客戶老是說在下載的過程中,過一會就出現(xiàn)崩潰的現(xiàn)象, 只要點了下載按鈕, 不做任何操作, 然后期刊就開始正常下載了,過大概5分鐘后,再去看,程序就已經(jīng)崩潰了)
在做《時裝傳媒》ipad應(yīng)用時,首頁的下載頁面,下載時,會不斷地去更新頁面上的下載進度,同時還有一個15秒的timer, 會每15秒切換當前顯示的是男裝,女裝或者藝術(shù)刊頁面。這個timer會把當前的scrollView中顯示的封面圖片進行移除,然后再替換,以實現(xiàn)自動更換首頁封面的功能
崩潰時提示:
Collection was mutated while being enumerated
(在網(wǎng)上搜了一下,發(fā)現(xiàn)有一個類似的問題:'NSGenericException', reason: '*** Collection <__NSArrayM: 0x8ef350> was mutated while being enumerated.')
根據(jù)這個提示, 想了一下,覺得應(yīng)該在做遍歷的過程中,修改了這個NSArray或者是NSMutableArray。后來想想, 這可能是多線程并發(fā)訪問時出現(xiàn)的問題, 沿崩潰時的堆棧找了一下,果然找到。
因為我們在下載時, 使用了Block每當接受到數(shù)據(jù),就去更新一下一個UIScrollView中的下載進度條的百分比。
而另有一個NSTimer, 會隔一段時間把這個UIScrollView中的全部元素清空,然后再重新添加, 因為可能有動態(tài)的元素需要添加或者刪除。
運行時, 就會出現(xiàn),兩個線程同時去訪問的情況, 當Block正在去更新UIScrollView中的這個元素時, NSTimer中可能正在執(zhí)行清除操作,所以就崩了。
原來,在同一時間,不同的線程同時讀取和修改了NSMutaleArray。
解決辦法:避免多線程同時去修改一個對象, 避免做遍歷時,這個對象被修改,根據(jù)這個思想,可以考慮加鎖,或者直接使用atomic的方式來做。