天天看點

iOS開發多線程篇—GCD的常見用法

一、延遲執行

1.介紹

ios常見的延時執行有2種方式

(1)調用nsobject的方法

[self performselector:@selector(run) withobject:nil afterdelay:2.0];

// 2秒後再調用self的run方法

(2)使用gcd函數

dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(2.0 * nsec_per_sec)), dispatch_get_main_queue(), ^{

// 2秒後異步執行這裡的代碼...

});

2.說明

第一種方法,該方法在那個線程調用,那麼run就在哪個線程執行(目前線程),通常是主線程。

[self performselector:@selector(run) withobject:nil afterdelay:3.0];

說明:在3秒鐘之後,執行run函數

代碼示例:

iOS開發多線程篇—GCD的常見用法
iOS開發多線程篇—GCD的常見用法

說明:如果把該方法放在異步函數中執行,則方法不會被調用(bug?)

iOS開發多線程篇—GCD的常見用法

第二種方法,

dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(5.0 * nsec_per_sec)), dispatch_get_main_queue(), ^{

//延遲執行的方法

說明:在5秒鐘之後,執行block中的代碼段。

參數說明:

iOS開發多線程篇—GCD的常見用法

什麼時間,執行這個隊列中的這個任務。

iOS開發多線程篇—GCD的常見用法
iOS開發多線程篇—GCD的常見用法
iOS開發多線程篇—GCD的常見用法

延遲執行:不需要再寫方法,且它還傳遞了一個隊列,我們可以指定并安排其線程。

如果隊列是主隊列,那麼就在主線程執行,如果隊列是并發隊列,那麼會新開啟一個線程,在子線程中執行。

二、一次性代碼

1.實作一次性代碼

需求:點選控制器隻有第一次點選的時候才列印。

實作代碼:

iOS開發多線程篇—GCD的常見用法
iOS開發多線程篇—GCD的常見用法

缺點:這是一個對象方法,如果又建立一個新的控制器,那麼列印代碼又會執行,因為每個新建立的控制器都有自己的布爾類型,且新建立的預設為no,是以不能保證改行代碼在整個程式中隻列印一次。

2.使用dispatch_once一次性代碼

使用dispatch_once函數能保證某段代碼在程式運作過程中隻被執行1次

static dispatch_once_t oncetoken;

dispatch_once(&oncetoken, ^{

// 隻執行1次的代碼(這裡面預設是線程安全的)

整個程式運作過程中,隻會執行一次。

iOS開發多線程篇—GCD的常見用法
iOS開發多線程篇—GCD的常見用法

效果(程式運作過程中,列印代碼隻會執行一次):

iOS開發多線程篇—GCD的常見用法

三、隊列組

需求:從網絡上下載下傳兩張圖檔,把兩張圖檔合并成一張最終顯示在view上。

1.第一種方法

iOS開發多線程篇—GCD的常見用法
iOS開發多線程篇—GCD的常見用法

顯示效果:

iOS開發多線程篇—GCD的常見用法

列印檢視:

iOS開發多線程篇—GCD的常見用法

問題:這種方式的效率不高,需要等到圖檔1.圖檔2都下載下傳完成後才行。

提示:使用隊列組可以讓圖檔1和圖檔2的下載下傳任務同時進行,且當兩個下載下傳任務都完成的時候回到主線程進行顯示。

2.使用隊列組解決

步驟:

建立一個組

開啟一個任務下載下傳圖檔1

開啟一個任務下載下傳圖檔2

同時執行下載下傳圖檔1\下載下傳圖檔2操作

等group中的所有任務都執行完畢, 再回到主線程執行其他操作

代碼示例

iOS開發多線程篇—GCD的常見用法
iOS開發多線程篇—GCD的常見用法

列印檢視(同時開啟了兩個子線程,分别下載下傳圖檔):

iOS開發多線程篇—GCD的常見用法

2.補充說明

有這麼1種需求:

首先:分别異步執行2個耗時的操作

其次:等2個異步操作都執行完畢後,再回到主線程執行操作

如果想要快速高效地實作上述需求,可以考慮用隊列組

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{

// 執行1個耗時的異步操作

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

// 等前面的異步操作都執行完畢後,回到主線程...

繼續閱讀