2017-02-23 61 views
1

需要在iOS主線程上運行任何與UI相關的工作。有時候,我們需要做一些異步工作怎麼樣下載圖像,我們可能會使用dispatch_async當下載完成,我們讓主線程,像這樣的事情顯示出來:uikit方法是否保證在主線程上運行?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
UIImage *overlayImage = [self faceOverlayImageFromImage:_image]; 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [self fadeInNewImage:overlayImage]; 
}); 

});}

但是,當我們在本地加載圖片,我們通常只是這樣做無需調度的主線程:

UIImageView *imageView = [[UIImageView alloc] initWithImage:@"myimage.png"]; 

我的問題是,他們都保證將在主線程上運行?如果是,爲什麼我們應該使用dispatch_get_main_queue()來分派它?如果沒有,爲什麼我們不需要在主線程上發送每個與UI相關的工作?

回答

6

你很困惑。

給定的調用鏈要麼在主線程上運行,要麼在後臺線程上運行。你處理的大部分代碼都是通過系統事件調用的,並且保證在主線程上運行。代碼將從後臺線程調用的情況數量有限。只有在這些情況下,您才需要將UIKit調用包含在將調用重定向到主線程的代碼中。

視圖控制器函數,按鈕操作等始終在主線程中調用。如果系統在後臺線程上調用某個方法,它將被記錄在案。

一些採用完成處理程序的函數會在後臺線程上調用這些完成處理程序。例如,NSURLSessionURLSession)類會調用其完成處理程序並在默認爲後臺線程的委託隊列上委派方法。所以當你將一個完成處理程序傳遞給URLSession的實例時,你需要確保你的UIKit代碼被打包到dispatch_async()(Swift 3中的DispatchQueue.main.async())或者將代碼傳遞給主線程執行的類似方法中。

+0

澄清:大多數情況下,您需要使用dispatch的原因是* you *啓動了後臺線程,並且該線程需要更改一些UI。除非通過一些處理切換到UI線程的回調來完成UI更改(例如進度條的setProgress),否則您必須使用分派。 – ToolmakerSteve

1

大多數UI相關的操作需要在主線程上執行才能正常工作。但簡單地使用UI...類本身並不確保它在主線程上運行。

這是您作爲程序員的工作。如果您在後臺執行某些操作(如下載數據或執行長時間運行的任務),然後需要更新UI,則必須確保UI代碼在主線程上完成。

請記住,創建UIImage實例可以安全地在後臺線程上創建。這很安全。

tl; dr - 不,沒有保證在主線程上運行。而且您確實需要在主線程上分派每個UI相關的工作,除非您已經在主線程中。

相關問題