dispatch source

1、它有什麼用
dispatch source 的作用是負責監聽事件,先看看它的構造函數。
[objc] view plaincopy在CODE上查看代碼片派生到我的代碼片

dispatch_source_create(dispatch_source_type_t type,  
uintptr_t handle,  
unsigned long mask,  
dispatch_queue_t queue);
   第1個參數:要監聽的事件類型
   第2個參數:可以理解爲句柄、索引或id,假如要監聽進程,需要傳入進程的ID
   第3個參數:根據參數2,可以理解爲描述,提供更詳細的描述,讓它知道具體要監聽什麼
   第4個參數:當事件發生時,將block添加至哪個隊列來執行

2、可監聽事件的類型

    DISPATCH_SOURCE_TYPE_TIMER        定時響應
    DISPATCH_SOURCE_TYPE_SIGNAL      接收到UNIX信號時響應

    DISPATCH_SOURCE_TYPE_READ   IO操作,如對文件的操作、socket操作的讀響應
    DISPATCH_SOURCE_TYPE_WRITE     IO操作,如對文件的操作、socket操作的寫響應   
    DISPATCH_SOURCE_TYPE_VNODE    文件狀態監聽,文件被刪除、移動、重命名
    DISPATCH_SOURCE_TYPE_PROC  進程監聽,如進程的退出、創建一個或更多的子線程、進程收到UNIX信號
    DISPATCH_SOURCE_TYPE_MACH_SEND
    DISPATCH_SOURCE_TYPE_MACH_RECV   上面2個都屬於Mach相關事件響應
    DISPATCH_SOURCE_TYPE_DATA_ADD
    DISPATCH_SOURCE_TYPE_DATA_OR          上面2個都屬於自定義的事件,並且也是有自己來觸發

3、怎麼使用

(一)自定義事件(DISPATCH_SOURCE_TYPE_DATA_ADD、DISPATCH_SOURCE_TYPE_DATA_OR),先看代碼
[objc] view plaincopy在CODE上查看代碼片派生到我的代碼片

dispatch_source_t source =dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());  
dispatch_source_set_event_handler(source,^{  
       NSLog(@"監聽函數:%lu",dispatch_source_get_data(source));  
});  
dispatch_resume(source);  

dispatch_queue_t myqueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL);  
dispatch_async(myqueue, ^ {  
      int i;  
      for(i = 0;i<</span>4;i++){  
         dispatch_source_merge_data(source,i);  
      }  
});  

首先使用dispatch_source_create函數創建 dispatchsource,第1個參數表示它是一個自定義的_ADD類型的監聽,具體作用後面說,2、3參數這裏面沒有作用設置爲0即可,第4個參數 表示一旦事件觸發就將要執行的代碼塊添加到主隊列中執行,接着我們使用dispatch_source_set_event_handler函數爲這個監 聽設置事件的源和響應體,第1個參數表示這個監聽是響應用戶自定義事件的,也就是我們上面定義的dispatchsource,第2個參數是負責響應的代 碼塊。很有意思的是當我們創建監聽後,這個監聽默認是掛起的,需要手動恢復,所以我們使用dispatch_resume函數恢復這個監聽,爲了測試這個 監聽,我們後面又通過for循環觸發事件,觸發事件的函數就是dispatch_source_merge_data,這個函數負責觸發自定義事件,第1 個參數表示要觸發哪個監聽,第2個參數是向監聽傳入一個unsigned long 類型的值, 我們這裏傳入循環的索引,好了,整體來看這段程序,dispatch_source_merge_data函數會被執行4次,並分別傳入0、1、2、3這 4個值,既然dispatch_source_merge_data負責觸發事件,那麼我們在監聽裏面的響應體應該會監聽到,結果也確實監聽到了,但是並 不是我們想象的那樣打印4次,而是隻打印了一次,打印結果是4次傳入值相加的和,也就是6,這就是 DISPATCH_SOURCE_TYPE_DATA_ADD參數的作用,這個監聽在創建之初就被設置爲自定義監聽,並且會把監聽結果相加,然後統一響 應。這裏你應該會奇怪,既然結果會相加並統一響應,那跟觸發的時候加好,然後觸發一次有什麼區別呢,好吧,我們把觸發事件的for循環改一下,然後再運 行,看看會發生什麼

[objc] view plaincopy在CODE上查看代碼片派生到我的代碼片

for(i = 0;i<</span>4;i++){  
    dispatch_source_merge_data(source,i);  
    [NSThread sleepForTimeInterval:0.0001];  
}  

我們在觸發事件的地方加上0.0001秒的延遲,然後運行整個程序多次,你會發現奇怪 的現象,我們同樣是觸發4次事件,但是響應的次數變成不確定了,可能是1次,也可能是2次,如果你將延遲時間設置長點,甚至設置爲0點幾秒就能讓響應的次 數變爲固定的4次,爲什麼會這樣呢,其實這就是這個自定義事件設計的初衷。如果同一時間同一個事件被觸發的頻率非常密集,那麼 dispatchsource會將這些密集的響應相加統計做出響應,但是如果觸發的相對零散,那麼dispatch source會分別進行響應,這其實是在智能的控制UI的沒必要的更新操作,因爲那些幾乎在同一時間更新進度條的操作完全可以統一進行更新,沒有必要每次 都更新一下。這樣做也會減少UI線程的負擔,例如更新進度條的同時,你的UI可能還在同時響應用戶的輸入、觸碰等工作。當然你可以選擇實時更新,辦法就是 直接使用使用dispatch_async直接更新界面。Dispatch source在統一響應完畢後計數變爲0,後面再觸發的會重新相加。DISPATCH_SOURCE_TYPE_DATA_OR會將所有監聽到的值邏輯與 操作,然後統一觸發。貌似沒有DISPATCH_SOURCE_TYPE_DATA_ADD常用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章