如何實現(xiàn)多個異步操作結束后執(zhí)行后續(xù)動作
場景:我們可能對列表中的數(shù)據(jù)進行批量操作后,執(zhí)行下一步操作。如多選刪除后,刷新頁面;如多選下載后,提示下載完成。
我們需要用到的一個核心的東西就是信號量:DispatchSemaphore
首先介紹下信號量
的基本語法
初始化
swift
let sema = DispatchSemaphore.init(value: 0)
oc
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
可以看出,我們傳了一個 Int 值用于初始化信號量。
兩個核心方法
swift
//等待
sema.wait()
//完成
sema.signal()
oc
//等待
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//完成
dispatch_semaphore_signal(sema);
wait
會對信號量 -1, -1后,如果信號量<0,則會阻塞線程
signal
會對信號量 +1
接著讓我們看下信號量
的簡單用法
1、單任務實例
以 swift 為例
//1
DispatchQueue.global().async {
//2
let sema = DispatchSemaphore.init(value: 0)
//3
NetManager.shared().checkPermission(withSpace: model.spaceType, andParentID: parentId, andChildenID: [modid], andAction: "copyFile2All", success: { (result) in
//4
sema.signal()
}) { (msg) in
//4
sema.signal()
}
//5
sema.wait()
//6
}
代碼解讀:
- wait 方法會阻塞主線程,所以需要放在子線程中,本例放在 global 中
- 創(chuàng)建信號量對象,信號量為 0
- 網絡請求的任務,使用的是AFNetworking
- 任務完成,信號量+1
- 信號量首先-1,然后檢測信號的值。當信號量<0時阻塞,并一直檢測信號量變化,直到信號量>0時,便會往后執(zhí)行,
- 注意:使用信號量,一定要放在子線程中,否則主線程會一直阻塞。
如上所示,我們可以在 注釋6
的位置寫上我們需要執(zhí)行的代碼。便達到了通過信號量等待一個任務完成后,執(zhí)行下一個任務的要求。
2、多任務實例
DispatchQueue.global().async {
let sema = DispatchSemaphore.init(value: 0)
for i in self.selectedItems {
NetManager.shared().checkPermission(withSpace: model.spaceType, andParentID: parentId, andChildenID: [modid], andAction: "copyFile2All", success: { (result) in
self.performSegue(withIdentifier: "showDirectoryTreevcID", sender: "copy")
sema.signal()
}) { (msg) in
//
sema.signal()
}
}
for _ in self.selectedItems {
sema.wait()
}
//刷新 UI 等操作可以放在這里(注:如果是對 UI 操作要放在主線程哦)
}
通過單任務實例
理解這個多任務的實例應該不難,在此不多做贅述。
總結
- 上例中的網絡請求方法只是實例用的,讀者可以自己寫個網絡請求替換掉
- 信號量有三個比較關鍵的點(信號量的值,wait 方法,signal 方法),理解透了用起來很簡單,且好用
- 信號量的初始化的值在本例中為 0,如果是正整數(shù),一般用于多任務線程池(比如同時最大支持n 個任務上傳)。