Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with multiple completion handlers

I'm trying to coordinate several completion handlers for each element in an array.

The code is essentially this:

var results = [String:Int]()

func requestData(for identifiers: [String])
{
    identifiers.forEach
    {   identifier in

        service.request(identifier, completion: { (result) in
            result[identifier] = result
        })
    }

    // Execute after all the completion handlers finish
    print(result)
}

So each element in the Array is sent through a service with a completion handler, and all the results are stored in an array. Once all of these handlers complete, I wish to execute some code.

I attempted to do this with DispatchQueue

var results = [String:Int]()

func requestData(for identifiers: [String])
{
    let queue = DispatchQueue.init(label: "queue")

    identifiers.forEach
    {   identifier in

        service.request(identifier, completion: { (result) in
            queue.sync
            {
                result[identifier] = result
            }
        })
    }

    // Execute after all the completion handlers finish
    queue.sync
    {
        print(result)
    }
}

but the print call is still being executed first, with an empty Dictionary

like image 997
XmasRights Avatar asked Nov 20 '17 02:11

XmasRights


People also ask

Can you explain completion handler?

A completion handler in Swift is a function that calls back when a task completes. This is why it is also called a callback function. A callback function is passed as an argument into another function. When this function completes running a task, it executes the callback function.

What is difference between closure and completion handler Swift?

As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn't called until the operation is completed—the closure needs to escape, to be called later.

How do I pass a completion handler in Swift?

Make a Completion handler : Create a completion handler closure and than pass it to function. Here we create an completion handler closure which type is () → Void . Now We will create a function which can take this closure .. Here we create a function which take a parameter of type () →Void .


1 Answers

If I understand what are you are trying to do correctly, you probably want to use a DispatchGroup

Here is an example:

let group = DispatchGroup()

var letters = ["a", "b", "c"]

for letter in letters {
    group.enter()
    Server.doSomething(completion: { [weak self] (result) in
        print("Letter is: \(letter)")
        group.leave()
    })
}

group.notify(queue: .main) {
    print("- done")
}

This will print something like:

b
c
a
// ^ in some order
- done
like image 192
Doug Mead Avatar answered Oct 09 '22 12:10

Doug Mead