Understanding sequence of operations with dependency in Swift

BaSha picture BaSha · Feb 14, 2017 · Viewed 7.2k times · Source

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

Answer

Ahmad F picture Ahmad F · Feb 14, 2017

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.