2012-06-20 30 views
16

我知道UIView不是線程安全的,所以我不能添加一個背景線程的視圖,解決這個問題可以在後臺線程上創建一個UIView然後將其添加到主線程?可以在後臺線程上創建UIView嗎?

注意:我不在主線程上這樣做的原因是因爲我的實際代碼更加複雜,因此需要一段時間才能創建所有視圖並填充值。當我這樣做時,我不希望UI變得無法響應,所以我試圖解決這個問題。

例如..

-(void)addLabel//called on background thread 
{ 
    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0,0,40,100)]; 
    [label setText:@"example"] 
    [self.view performSelector:@selector(addSubview:) onThread:[NSThread mainThread] withObject:example waitUntilDone:YES]; 
} 

預先感謝。

+0

我相信你是對的。在後臺創建它,但更新主要的UI。 –

回答

15

UIView

線程注意事項

操作,以應用程序的用戶界面必須發生在主線程。因此,您應該始終從應用程序主線程中運行的代碼中調用UIView類的方法。唯一不是嚴格需要的時候是創建視圖對象本身,但所有其他操作應該在主線程上進行。

initWithFrame:的調用明確地不是線程安全的。致電setText:可能不是線程安全的,屬於「操縱」條款。這些肯定不是線程安全的。

做你的工作來找出後臺線程上的數據。然後在主線上創建你的觀點。如果有大量的視圖,您可以嘗試使用幾個dispatch_async()調用將主要隊列分解。這可能會讓UI保持響應;我沒有廣泛地嘗試過它。

如果可能,您可能還需要考慮從UIView切換到CALayer。大多數CALayer工作可以在後臺線程上完成。如果您有大量的意見,那可能無效。如果只是需要很長時間才能計算視圖的數據,則表明您沒有正確分離模型和視圖信息。 Model類應該計算獨立於創建視圖所需的所有內容。

+5

對不起,但你能澄清你的答案?蘋果特別提到,在後臺創建視圖是可以的,但你說的不是。爲什麼? –

+0

@iamataptool可能你可以用'init'方法安全地創建UIView,但不能用'initWithFrame:'方法? – DanSkeel

+0

CALayer提示使我的一天和一週。非常感謝! –

0

Drawing and Printing Guide狀態:

重要的UIKit類一般不是線程安全的。所有與繪圖相關的操作應該在應用程序的主線程上執行。

因此,據我所知,唯一的問題似乎與「繪圖相關的操作」有關。如果我們假設一個正確的類只在其drawRect:方法中執行這樣的操作,那麼您建議的方法應該沒問題。

+0

在我的情況下,我的應用程序通過'UIApplicationLaunchOptionsLocalNotificationKey'喚醒,所以它在後臺。是否可以,如果我在應用程序在後臺時執行子視圖添加? https://stackoverflow.com/questions/46584566/how-to-stop-handle-ui-operations-in-ios-when-app-moves-to-background-state – Nil

3

我使用Xcode版本9.0 beta 3(9M174d),收到警告。

[UView的init]必須從主線程中調用僅

所以我認爲你應該建立在主線程UI更好

顯示如下圖所示:

enter image description here

相關問題