toast toast - 17 days ago 6
iOS Question

How to use DispatchGroup to make asynchronous calls within a for loop

In my example code below, I call

complete(false)
on failure. However, since I'm using a
DispatchGroup
object to make sure all asynchronous requests are complete, I cannot just call
syncGroup.leave()
on failure, as the
notify
will be called, which contains
complete(true)
, making this function return
true
, when it should be returning
false
for failure.

Am I correct in not calling
syncGroup.leave()
on failure to complete my function correctly? Or should I be calling
syncGroup.leave()
and somehow trying to determine what the result is, so I can return
false
on failure?

let syncGroup = DispatchGroup()
syncGroup.enter()
for track in unsynced {
register(time: time, withCompletion: { (success: Bool) -> () in

if success {
self.debug.log(tag: "SyncController", content: "Registered")
syncGroup.leave()
}
else {
complete(false)
}
})
}

//all requests complete
syncGroup.notify(queue: .main) {
self.debug.log(tag: "SyncController", content: "Finished registering")
complete(true)
}

Answer

You have to enter the group within your for loop. You might want to introduce an additional error flag.

Example implementation:

    var fail = false
    let syncGroup = DispatchGroup()

    for track in unsynced {
        syncGroup.enter()
        register(time: time, withCompletion: { (success: Bool) -> () in

            if success {
                self.debug.log(tag: "SyncController", content: "Registered")
                syncGroup.leave()
            }
            else {
                fail = true
                syncGroup.leave()
            }
        })
    }

    //all requests complete
    syncGroup.notify(queue: .main) {
        if fail {
            complete(false)

        } else {
            self.debug.log(tag: "SyncController", content: "Finished registering")
            complete(true)
        }
    }
Comments