Ở phần 1 của bài viết, mình đã giới thiệu về Operation là gì. Ở phần 2 của loạt bài về Operation, mình sẽ nói về Dependency trong Operation.
Nội dung bài viết:
- Operation Dependencies
- Passing Data using Dependencies
Operation Dependencies:
Operation cho phép bạn thiết lập các sự phụ thuộc lẫn nhau. Điều này mang lại 2 lợi ích:
- Giả sử operation 2 phụ thuộc vào operation 1. Khi đó operation 2 chỉ được thực hiện sau khi operation 1 đã hoàn thành.
- Cung cấp 1 cách để bạn truyền data giữa các operation.
class DownloadImage: Operation {
var index: Int
init(ind: Int) {
self.index = ind
}
override func main() {
// Download image task
print("Start downloading task \(index) at time: \(Date().timeIntervalSince1970)")
sleep(5)
print("Finish downloading task \(index) at time: \(Date().timeIntervalSince1970)")
}
}
let firstOperation = DownloadImage(ind: 1)
let secondOperation = DownloadImage(ind: 2)
//firstOperation.addDependency(secondOperation)
let operationQueue = OperationQueue()
operationQueue.addOperation(firstOperation)
operationQueue.addOperation(secondOperation)
Ở trên là đoạn code khởi tạo 2 operation bình thường, giữa chúng chưa có dependency. Chạy đoạn code trên và đây là kết quả thu được:
![](https://i1.wp.com/s3-ap-southeast-1.amazonaws.com/techover.storage/wp-content/uploads/2020/02/22104959/Screen-Shot-2020-02-22-at-10.21.25.png?fit=1024%2C77&ssl=1)
Giờ thì bỏ comment dòng code firstOperation.addDependency(secondOperation) và chạy thử:
![](https://i1.wp.com/s3-ap-southeast-1.amazonaws.com/techover.storage/wp-content/uploads/2020/02/22105136/Screen-Shot-2020-02-22-at-10.21.50.png?fit=1024%2C84&ssl=1)
Note: Bạn có thể tạo dependency cho 2 opeartion đang chạy ở 2 operation queue khác nhau.
Đây là 1 cách khá ngắn trong khi ở GCD bạn phải khai báo 1 dispatchGroup, sau đó gọi hàm enter(), leave(), notify(), … Tuy nhiên, cách làm này rất dễ gây ra deadlock.
Để remove 1 dependency, bạn chỉ cần gọi:
firstOperation.removeDependency(op: secondOperation)
![](https://i1.wp.com/s3-ap-southeast-1.amazonaws.com/techover.storage/wp-content/uploads/2020/02/22110923/Screen-Shot-2020-02-22-at-10.23.17.png?fit=1024%2C286&ssl=1)
![](https://i0.wp.com/s3-ap-southeast-1.amazonaws.com/techover.storage/wp-content/uploads/2020/02/22105421/Screen-Shot-2020-02-22-at-10.23.05.png?fit=1024%2C364&ssl=1)
Ở đoạn code mẫu ở trên, nếu bạn sửa đoạn code thành như dưới đây thì code của bạn sẽ bị deadlock và không chạy.
firstOperation.addDependency(secondOperation)
secondOperation.addDependency(firstOperation)
Note: Hãy vẽ sơ đồ ra 1 tờ giấy để luôn clear về flow của bạn, tránh bị deadlock.
Truyền data giữa các operation thông qua dependency:
class Calculate: Operation {
let firstNum: Int
let secondNum: Int
var sum: Int?
init(first: Int, second: Int) {
self.firstNum = first
self.secondNum = second
}
override func main() {
sum = firstNum + secondNum
}
}
class Display: Operation {
override func main() {
// 2
let sum = dependencies.compactMap{ ($0 as? Calculate)?.sum }.first
guard let unwrappedSum = sum else {
return
}
// 3
print("Sum = \(unwrappedSum)")
}
}
let calculateOperation = Calculate(first: 5, second: 10)
let displayOperation = Display()
// 1
displayOperation.addDependency(calculateOperation)
let operationQueue = OperationQueue()
// 4
operationQueue.addOperation(calculateOperation)
operationQueue.addOperation(displayOperation)
- Khởi tạo 2 operation, và set dependency để task Display chỉ chạy sau khi task Calculate hoàn thành.
- Hàm main() là hãm sẽ chạy khi 1 operation được chạy.
Ở đây, ta sẽ lấy ra list operations có dependency với DisplayOperation, chọn ra operation nào là Calculate và lấy ra sum. - Nếu sum khác nil thì hiển thị ra.
- Add các operation vào queue để chạy.
Kết quả hiển thị trên màn hình Console:
![](https://i0.wp.com/s3-ap-southeast-1.amazonaws.com/techover.storage/wp-content/uploads/2020/02/22110823/Screen-Shot-2020-02-22-at-11.08.09.png?fit=1024%2C72&ssl=1)
Dependency trong Operation là 1 trong những thứ giúp Operation vượt trội hơn so với GCD.
Ở phần tiếp, mình sẽ nói về Async Operation và xử lí cancel Opeartion.