Adding dependency of one BlockOperation on another is not working properly in swift

872 views Asked by At

I have multiple api's in a controller and after successful response I have to reload the UITableView.

For now I started with two api having second api dependency on first one using BlockOperation and DispatchGroup in it.

First in viewDidLoad:

getDataFromAllApis {
    self.tableView.reloadData()
}

Then I added the method:

func getDataFromAllApis(completion: @escaping (() -> Void)) {

    let queue = OperationQueue()

    let getFirstDataOperation = BlockOperation {
        let group = DispatchGroup()
        group.enter()
        self.getFirstDataFromApi {
            group.leave()
        }
        group.wait()
    }
    queue.addOperation(getFirstDataOperation)

    let getSecondDataOperation = BlockOperation {
        let group = DispatchGroup()
        group.enter()
        self.getSecondDataFromApi {
            group.leave()
        }

        group.notify(queue: .main) {
            completion()
        }
    }
    queue.addOperation(getSecondDataOperation)

    getSecondDataOperation.addDependency(getFirstDataOperation)
}

The problem that I am facing here is getSecondDataOperation executes first and returns to the tableview reload part.

Am I missing something here or there can be a different approach for it? Any help will be appreciated.

I have tried going through this post :

1

There are 1 answers

6
matt On BEST ANSWER

You are way overthinking this. Just call the second API from the completion handler of the first API. No operations, no dispatch groups, no nothing.

self.getFirstDataFromApi {
    self.getSecondDataFromApi {
        // call the completion handler
    }
}

As for why your code didn't work, it's because you didn't do what the linked answer said to do!

How can you use Dispatch Groups to wait to call multiple functions that depend on different data?

It said to do this:

getSecondDataOperation.addDependency(getFirstDataOperation)
queue.addOperation(getFirstDataOperation)
queue.addOperation(getSecondDataOperation)

That isn't what you did. You did this:

queue.addOperation(getFirstDataOperation)
queue.addOperation(getSecondDataOperation)
getSecondDataOperation.addDependency(getFirstDataOperation) // too late

(However, that post, while ingenious, is not what I would do in this situation. If I wanted to sequentialize download operations, I would use the technique described here: https://fluffy.es/download-files-sequentially/. Or, in iOS 13, I'd use the Combine framework, as I describe here: https://stackoverflow.com/a/59889993/341994.)