2010-04-30 110 views
4

從後臺線程調用deallocUIViewController上是錯誤的嗎?似乎UITextView(可以嗎?)最終調用_WebTryThreadLock這會導致:dealloc在後臺線程

布爾_WebTryThreadLock(布爾):試圖從一個線程 比主線程或web線程以外獲得網絡鎖定。這可能是從輔助線程調用 到UIKit的結果。

背景:我有一個子類NSOperation,需要一個selectortarget對象來通知。

-(id)initWithTarget:(id)target { 
    if (self = [super init]) { 
     _target = [target retain]; 
    } 
    return self; 
} 

-(void)dealloc { 
    [_target release]; 
    [super dealloc]; 
} 

如果UIViewControllerNSOperation得到各地的跑步已經被開除,然後調用release觸發它的dealloc在後臺線程。

+0

[我的解決方案(使用NSTimer強制最後一個發佈到主線程上)](http:// stackoverflow。com/questions/6353471/block-release-deallocating-ui-objects-on-a-background-thread/6482941#6482941「My solution」) – Jeff 2011-06-26 08:44:54

回答

7

是的,在後臺線程(或隊列)中釋放UIViewController是錯誤的。在UIKit中,dealloc不是線程安全的。這是在蘋果的TN2109文檔明確描述:

當輔助線程保留目標對象,你必須確保線程釋放主線程之前參考釋放它的最後一個引用的對象。如果不這樣做,則最後一個對象的引用由輔助線程釋放,這意味着該對象的-dealloc方法在該輔助線程上運行。如果對象的-dealloc方法在輔助線程上執行的操作不安全,這對於UIKit對象(如視圖控制器)來說很常見,這是有問題的。

+1

4年後,出現正確答案!不錯的工作 - TN在我的問題後幾個月發佈,所以看起來我並不是唯一一個被這種行爲困惑的人。 – 2014-06-25 14:21:21

6

簡單的規則是從後臺線程UI*是一個錯誤。

+0

'performSelectorOnMainThread'怎麼樣?這是記錄在任何地方?我所看到的只是對「不要在後臺線程中操作UI」的模糊引用 - 這比你的*任何*限制性要少得多。 – 2010-05-02 16:47:27

+2

這是調用performSelectorOnMainThread的常用方法:如果你想從後臺線程操作UI。 – schaechtele 2010-05-03 14:42:38

+0

@schaechtele - 當你從一個不同的對象進行跨線程調用時,你是在調用[UIViewController performSelectorOnMainThread:]還是[self performSelectorOnMainThread:]? – 2010-05-03 18:55:29

3

這裏的第二篇文章有一些有用的信息,但他們的回答對我來說並不適用。

UIWebView in multithread ViewController

這也似乎是,這可能在iPhone OS 4已經得到解決,但不能肯定。

當[N​​SThread isMainThread]爲NO時,我最終沒有在控制器的dealloc中釋放我的UIWebView。寧願泄漏比崩潰(直到我得到一個更好的解決方案)。

+0

是的 - 同樣的問題。我通過在主線程中釋放來解決這個問題,但我認爲,對於sutorekease也同樣適用。 我主要關心的是它是否是預期的行爲,在ObjC中。我應該檢查iPhone 4,看看它是否發生了變化 - 至少可以說明這是一個錯誤。 – 2010-05-26 22:10:35

+0

我認爲這是iOS4的「固定」,至少基於粗略測試 – Jason 2010-06-12 15:45:24

2

在任何時候調用dealloc都是錯誤的。你只應該打電話發佈。

您不應該從後臺線程訪問任何與UI相關的實例。這包括使用getter方法,因爲它們可能會在內部修改內容。但是,只要遵循正常的保留和釋放規則,保留和釋放對任何對象都是線程安全的。與UI相關的實例包括由活動UIView或UIViewController引用的任何對象。

performSelectorOnMainThread除了保留一個對象直到它到達主線程之外不會做任何事情。調用任何與UI相關的對象是安全的。

+0

沒錯。我只調用release,但是因爲它是最後一個版本,所以最終在內部調用dealloc。如果release是線程不可知的,那麼dealloc必須是正確的 - 對嗎?那麼,_WebTryThreadLock只是規則的一個例外(可能是越野車)? – 2010-05-26 22:07:55