Search code examples
swiftloopstimerdelaydispatch-queue

Using dispatchQueue in loops


I am attempting to loop something with a delay (just as a proof of concept) this is for something else. But to simplify it, here is an example.

so in this example, I have a string with "text" and I want to loop the addition of another string lets say 10 times. The only thing is that I want there to be a delay in each iteration. here is my code thus far.

// global variable

var myString = "text"

// an action inside a button

    let delayInSeconds = 1.0
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayInSeconds) {

        for _ in 1...10 {
           self.myString += "another text"
        }
    }
    labelOne.text = myString

}

I should add that the result is that all 10 "another text" are added immediately without any delay.

thank you


Solution

  • In your example, you append your string ten times in the same work unit. Try dispatching work once per loop:

    for delay in 1...10 {
        let delayInSeconds = Double(delay)
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayInSeconds) {
            self.myString += "another text"
            labelOne.text = myString
        }
    }
    

    This loop won't work well for arbitrarily large values, though. It also doesn't provide the kind of precise timing we might want for user interface changes. For that, we can use Timer. Here’s the same problem reworked with Timer:

    // Add to the class body…
    var i = 1
    // Lazy initialization so the timer isn’t initialized until we call it
    lazy var timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {timer in
        guard self.i <= 20 else {
            timer.invalidate()
            return
        }
    
        self.label.text?.append(" another text")
        self.i += 1
    }
    
    // Add to the button action…
    timer.fire()