2009-11-10 32 views
3

這實在是奇怪...iPhone UI addSubview引起併發異常

我跑我的應用程序,雖然它是開放和看法正在建設,我得到:

Collection <CALayerArray: 0x124650> was mutated while being enumerated. 

代碼trace經歷以下:

main 
UIApplicationMain 
-[UIApplication _run] 
CFRunLoopRunInMode 
CFRunLoopRunSpecific 
_UIApplicationHandleEvent 
-[UIApplication sendEvent:] 
-[UIApplication handleEvent:withNewEvent:] 
-[UIApplication _runWithURL:sourceBundleID:] 
-[UIApplication _performInitilizationWithURL:sourceBundleID:] 
-[AppDelegate applicationDidFinishLaunching:] 
+[Controller initializeController] //This is my own function 
    [window addSubview: pauseMenuController.view] //This is the last point of my code it goes through 
-[UIView(Hierarchy) addSubview:] 
-[UIView(Internal) _addSubview:positioned:relativeTo:] 
-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:] 
-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] 
-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] 
_NSFastEnumerationMutationHandler 
objc_exception_throw 

我運行遊戲很多,很多,很多次,我從來沒有見過這個,然後突然就彈出。奇怪的是,我沒有創建任何其他線程(我知道),直到之後這個代碼全部被調用。如果有人能夠給我一些關於在UIView中訪問時可能會被修改的解釋,我將更容易進行調試。在添加視圖的同時,它已經添加了一些東西,也許它有什麼關係?有任何想法嗎?

+0

當你得到錯誤時,你能詳細說明應用程序行爲有什麼不同嗎?崩潰...沒有看到...等... – coneybeare 2009-11-10 23:54:06

+0

你能發表一些代碼嗎?調用-addSubview的簡單行爲不會導致這個問題,如果沒有代碼,我們只能盲目猜測。 – 2009-11-10 23:57:53

回答

4

這不是併發異常。當某些東西(可能在同一個線程的循環中)改變循環迭代的數組/字典時,就會發生枚舉變異異常。

由於addSubview:在堆棧中,我的猜測是有些東西試圖在構造過程中刪除UIView的子視圖之一。

你是否覆蓋了可能正在運行的任何方法?像addSubview或可能layoutSubviews?如果其中任何一項是刪除子視圖,那麼這會導致問題。

+2

輝煌,那是問題,謝謝!我認爲這是一個併發問題,因爲通常爲了在訪問時需要多個線程而進行變異,但是你說的並非總是如此。 – Eli 2009-11-11 16:26:02

+0

完全準確。我有同樣的問題。在我的情況下,添加視圖的viewController實際上已經搞亂了superview的佈局。非常感謝。你爲我節省了幾個小時的痛苦。 – Pacu 2011-01-19 03:27:29

16

是否有可能您的視圖有一個子圖層,您將代理指定爲視圖?這通常會導致視圖在調用_makeSubtreePerformSelector:withObject:withObject:copySublayers:時無限遞歸(好吧,直到它達到堆棧限制),但我認爲可能的是,無論它試圖在這裏做什麼都涉及到變異。

這是因爲UIView假定如果一個CALayer的委託是一個UIView,那麼該CALayer屬於UIView和UIView是層次結構的一部分。但是,如果您創建自己的CALayer並將該委託分配給UIView,那麼UIView將最終調用自身作爲遞歸的一部分。

+0

絕對是一個很好的迴應,但如果你說的是這樣的話,那麼每一次都會發生這種情況。事實上,它只發生過數百次或數千次運行中的一次。嗯。 – Eli 2009-11-10 22:56:09

+1

Kevin對UIView層次結構re delegates的解釋幫助我解決了一個切題:我添加了一個CALayer作爲視圖圖層的子圖層,並將該控制器作爲委託來分配。雖然在viewDidUnload/dealloc上,我在子圖層之前取消了/釋放了視圖,但是我在'_makeSubtreePerform ... copySublayers'上崩潰了。解決方案是在取消任何操作之前刪除子層*。據推測,這阻止了控制器作爲委託來調用釋放的子層。 – Wienke 2012-05-12 14:10:06

0

從文檔:

枚舉是「安全的」誠枚舉具有突變後衛,這樣,如果你試圖枚舉過程中修改集合,則會引發異常情況。

基本上,這意味着當您使用Objective-C 2.0中引入的快速枚舉來枚舉集合時(例如數組),不允許添加/刪除對象。因爲這樣做會使變異守衛失效。

就你而言,集合與視圖層次結構相關。如果你想添加和/或刪除視圖到這個特定的集合,不要使用快速枚舉。

+0

我知道第一部分,快速列舉發生在蘋果方面,而不是我的方面。 – Eli 2009-11-10 22:55:03

0

我在CALayer的-dealloc方法中嘗試清除屬性時,發現CALayers中發生了這種情況,只是更改該屬性而無意中改變了圖層的可見屬性。您可以檢查並查看您是否在某種情況下在某個視圖的-dealloc期間更改了某個視圖的屬性。

0

我遇到了同樣的錯誤。我在非主線程上改變了視圖層次結構。確保視圖的所有修改都在主線程上執行。