Operation支持以下三種添加任務的方式
- 傳
Operation - 傳閉包
- 傳
Operation數(shù)組
Operation管理
OperationQueue會根據(jù)QoS優(yōu)先級以及其它依賴來執(zhí)行狀態(tài)為isReady的Operation。每個Operation只能被執(zhí)行一次,所以如果一個Operation實例被添加到了一個隊列中,那么它就不可以再被添加到別的隊列中了。所以重復執(zhí)行的任務可以通過實例化多個Operation子類來達到目的。
等待完成
如果看OperationQueue的底層,你會發(fā)現(xiàn)一個方法叫waitUntilAllOperationsAreFinished。這個方法的調用會阻塞當前線程,所以不要在主線程調用。如果真的需要,就重新啟用一個串行隊列來調用它。
優(yōu)先級
OperationQueue就像DispatchGroup,任務會有不同的QoS優(yōu)先級。
默認的優(yōu)先級是.background,類似DispatchGroup,隊列的優(yōu)先級可能會因為任務的優(yōu)先級更高而被升級來匹配。
暫停
設置isSuspended屬性為true將會在暫停隊列后續(xù)任務的執(zhí)行。當前正在處理的任務還會繼續(xù),后續(xù)的任務知道isSuspended為false才會繼續(xù)執(zhí)行
最大Operation數(shù)
默認情況下,DispatchQueue的最大任務數(shù)和設備能支持的并發(fā)數(shù)一樣。
設置maxConcurrentOperationCount即可限制。當它為1的時候,這個隊列就相當于是一個串行隊列。
underlyingQueue
在還沒有添加operation之前,把一個已經存在的DispatchQueue隊列設置為underlyingQueue會使得OperationQueue里的所有任務QoS優(yōu)先級與DispatchQueue優(yōu)先級相同。這樣設置可以將一系列不同的優(yōu)先級的任務根據(jù)DispatchQueue來重新設定。
例子
下面的代碼在UITableView上展示經過濾鏡過濾的圖片,原圖片從本地讀取,濾鏡圖片則是實時渲染。
如果在主線程直接渲染會引起卡頓,這里通過OperationQueue實現(xiàn)異步渲染和加載
例子中建立的默認參數(shù)Operation隊列是串行的
class FilterTableViewController: UITableViewController {
private let queue = OperationQueue()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "example", for: indexPath) as! PhotoCell
let image = UIImage(named: "\(indexPath.row).png")!
let op = FilterOperation(image: image)
op.completionBlock = { // Operation完成閉包
DispatchQueue.main.async
{
guard let cell = tableView.cellForRow(at: indexPath) as? PhotoCell else {
return
}
cell.update(image: op.outputImage)
}
}
queue.addOperation(op) // 不需要主動調start(),加入隊列之后就會根據(jù)系統(tǒng)資源安排執(zhí)行
return cell
}
}
final class FilterOperation: Operation {
private static let context = CIContext()
var outputImage: UIImage?
private let inputImage: UIImage
init(image: UIImage) {
inputImage = image
super.init()
}
override func main() {
guard let filter = Filter(image: inputImage, radius: 3), // CIFilter封裝
let output = filter.outputImage else {
print("Failed to generate tilt shift image")
return
}
let fromRect = CGRect(origin: .zero, size: inputImage.size)
guard let cgImage = TiltShiftOperation.context.createCGImage(output, from: fromRect) else {
print("No image generated")
return
}
outputImage = UIImage(cgImage: cgImage)
}
}
系列文章鏈接
- Swift多線程開發(fā) - 1. 概述
- Swift多線程開發(fā) - 2. GCD 隊列和線程
- Swift多線程開發(fā) - 3. DispatchGroup和Semaphore
- Swift多線程開發(fā) - 4. 多線程開發(fā)的問題
- Swift多線程開發(fā) - 5. Operations
- Swift多線程開發(fā) - 6. Operation 隊列
- Swift多線程開發(fā) - 7. Operation 異步隊列
- Swift多線程開發(fā) - 8. Operation依賴
- Swift多線程開發(fā) - 9. 取消Operation
- Swift多線程開發(fā) - 10. Thread Sanitizer