Reversed loop reverts back inside Dispatch Queue

It's seems an odd phenomena, I tried both the reversed() method and Stride:

        for num in stride(from: 20, to: 0, by: -1) {
        //for num in (1...20).reversed() {
            print("BEFORE DISPATCH \(num)")
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(num)) {
            print("AFTER DISPATCH \(num)")
            }
        }

The only workaround I have is to print out "(20-num)".

What is going on ?

You’re telling Dispatch when to run some things, and it’s running those things at those times.

I think I get what you're asking. I ran your code and I get the BEFORE DISPATCH part counting down, then I get the AFTER DISPATCH counting up. If you take out the + Double(num) that's creating the delay, then you get the AFTER DISPATCH in a countdown, too (almost instantaneously). Since your delay for the largest numbers are the longest, they come out last, and since this code is basically instantaneous you get the last ones that have the shortest delay finishing first (the lower numbers at the end) and working backward toward the ones with a longer delay. If you want this to go 20 down to 1 and then again but with a second tick in-between then have the delay set so the one with the biggest number has the shortest delay. That is, change your deadline: calculation to .now() + Double(20-num) so the 20 has the shortest delay of 0 and the 1 has the longest delay of 19.

1 Like

So basically reverse the workaround ?

It's so confusing, but thanks for the explanation.

Around 14:35 this video goes into a little bit of that : Dispatch Groups in Swift 5: iOS Concurrency (2020 Xcode 11, Swift 5) - YouTube

The workaround? I’m not sure what the workaround is. Just making sure that the delay is set so the ones you’d like to start first have the shortest delay. Also keep in mind these timings are not a guarantee. I’m not sure exactly what the contract is but you definitely should not rely on them being down to the millisecond.

What is it that you expected to happen? You never explained that. The behavior of the code is easily and intuitively predictable to me.

Because you explicitly print "n" with a delay of n seconds, it does not matter how the jobs are enqueued, it always prints 1 to n as time elapses.