Referring https://developer.apple.com/reference/foundation/operation, I am having Playground setup as -
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.addOperation(op2)
And console log is -
op1 working....
op2 working....
op1 finished
op2 finished
Shouldn't we expect output as result of dependency? -
op1 working....
op1 finished
op2 working....
op2 finished
Same result with using - opsQue.addOperations([op1, op2], waitUntilFinished: true)
op1 working....
op2 working....
op1 finished
op2 finished
In fact, I can't determine what's exactly the mystery of why your code does not work as it should, but I figured out 3 workarounds to achieve what are you trying to:
If you are expecting that the output should always be:
op1 working....
op1 finished
op2 working....
op2 finished
then:
1- You might want to add the second operation to the queue in the completion block of the first one, as follows:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let opsQue = OperationQueue()
let op1 = myOperation1()
op1.completionBlock = {
print("op1 finished")
opsQue.addOperation(op2)
}
let op2 = myOperation2()
op2.completionBlock = {
print("op2 finished")
}
opsQue.addOperation(op1)
2- Setting maxConcurrentOperationCount operation queue to 1, as follows:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
// setting maxConcurrentOperationCount to 1
opsQue.maxConcurrentOperationCount = 1
opsQue.addOperation(op1)
opsQue.addOperation(op2)
3- Calling waitUntilAllOperationsAreFinished() after adding the first operation to the queue, as follows:
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.waitUntilAllOperationsAreFinished()
opsQue.addOperation(op2)
btw, for a non-complex task, I prefer to use GCDs.
Hope this helped.
The completion block is called after the dependancy operation starts, but it doesn't mean that the first operation didn't end.
As quoted in @Xoronis's answer:
The exact execution context for your completion block is not guaranteed but is typically a secondary thread. Therefore, you should not use this block to do any work that requires a very specific execution context.
https://developer.apple.com/documentation/foundation/operation/1408085-completionblock
Take a look at this example:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
for i in 1...10 {
print("\(i)")
}
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 completed")
}
op2.completionBlock = {
print("op2 completed")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperations([op1, op2], waitUntilFinished: true)
will result in
op1 working....
1
2
3
4
5
6
7
8
9
10
op2 working....
op1 completed
op2 completed
The first operation does end before starting its dependancy, but the completion block is called after the dependancy already started.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With