Search code examples
swiftdispatch-async

How to wait for completion handler to finish? Dispatch.group?


I need help altering my code so that it waits for the completion handler to fire, before looping.

Problem

I am trying to run the following block of code:

let sourceCodes:[String] = self.makeCodeArray(codeString: (self.sourceDict?["Code"]!)!)

print("A")
for i in 0..<sourceCodes.count
{
    print("B")
    getRealtimeData(stopCode: sourceCodes[i], completion:
    {
        (realtimeSourceResult) in

        print("C")
        self.overallSourceResult.append(realtimeSourceResult)

        if i == sourceCodes.count - 1
        {
            print("D")
        }
        else
        {
            print("K")
        }
    })
}

so that the output is:

A
B
C
K
B
C
K
B
C    (BCK repeating until the last iteration)
K
...
B
C
D

However, currently the code is executing in the following order: A B B B B ... C K C K C K C D

How would I change my code so that it executes in the desired manner? I have tried using Dispatch.group but I cannot seem to get that working either.

Here is my attempted solution using Dispatch.group

let sourceCodes:[String] = self.makeCodeArray(codeString: (self.sourceDict?["Code"]!)!)
let group = DispatchGroup()

print("A")
for i in 0..<sourceCodes.count
{
    group.enter()

    print("B")
    getRealtimeData(stopCode: sourceCodes[i], completion:
    {
        (realtimeSourceResult) in

        print("C")
        self.overallSourceResult.append(realtimeSourceResult)

        if i == sourceCodes.count - 1
        {
            print("D")
        }
        else
        {
            group.leave()
            print("K")
        }
    })
}

Thanks in advance for any help!


Solution

  • You need to use group.wait(). And you need to move your group.leave() so it always called. leave must be called for each enter or the wait will never stop waiting.

    print("A")
    for i in 0..<sourceCodes.count
    {
        group.enter()
    
        print("B")
        getRealtimeData(stopCode: sourceCodes[i], completion:
        {
            (realtimeSourceResult) in
    
            print("C")
            self.overallSourceResult.append(realtimeSourceResult)
    
            if i == sourceCodes.count - 1
            {
                print("D")
            }
            else
            {
                print("K")
            }
    
            group.leave() // always call this
        })
    
        group.wait() // don't iterate until the completion handler is done
    }