8

I have this delay function:

func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
           DISPATCH_TIME_NOW,
           Int64(delay * Double(NSEC_PER_SEC))
    ),
    dispatch_get_main_queue(), closure)
}

From here: dispatch_after - GCD in swift?

This code:

func start(){
   for index in 1...3 {
      delay(3.0){
         println(index)
      }
   }
}

After 3 sec, it gives:

3

3

3

My Goal:

After 3 sec: 1

After 6 sec: 2

After 9 sec: 3

How whould I achieve this? Thank You,

Community
  • 1
  • 1
Zoltan
  • 533
  • 4
  • 18
  • 2
    Finally a basic question including all **relevant code**, practically a MCVE, the **current output** as well as the **desired output**. Well asked! – luk2302 Apr 28 '16 at 14:28
  • I assume that the delay function is from http://stackoverflow.com/a/24318861/1187415, in that case you should add a link to your question, for proper attribution. – Martin R Apr 28 '16 at 14:46
  • Have you considered NSTimer? – Will M. Apr 28 '16 at 14:53
  • Please do not include the answers given in your question. That is what the answer section is for. If you have additions to the answers, comment on them. If you came up with a new unique solution based on the other answers, then post an answer on your own. – luk2302 Apr 29 '16 at 10:18

3 Answers3

6

try multiplying delay with index

func start(){
   for index in 1...3 {
      delay(3.0 * index){
         println(index)
      }
   }
}
Shubhank
  • 21,721
  • 8
  • 65
  • 83
  • That code does not really answer the question. Indeed multiplying by the index has no effect for the value of index that gets captured on each time the delay function's closure is executed. – mz2 Apr 28 '16 at 14:54
  • Ah, I misunderstood a part of the question, I'll adjust my vote as soon as the 15min interval's gone… I thought the issue concerned only seeing value "3" being repeatedly printed (instead of 1,2,3) – this does not actually happen with the current version of Swift. – mz2 Apr 28 '16 at 15:07
  • Also, your solution also captures `index` in each of the for loop's iterations (as part of computing the return value for the `3.0 * index` expression) so the behaviour where the last value of the index would get repeatedly passed to the print statement is also not happening for that reason there. – mz2 Apr 28 '16 at 15:13
  • Thank you, I used another type of for loop: `for var index = 0; index < 3; index++` With for ... in it works with `delay(3.0 * Double(index))` – Zoltan Apr 28 '16 at 15:38
  • Right, that would indeed explain why you'd have seen `3` repeatedly in output. Good stuff. – mz2 Apr 29 '16 at 11:15
3

If you are (bizarrely) seeing 3 as the value of index that gets printed out on each of the iterations of the loop, you can do the following to ensure the correct (current) value of the iterator variable gets captured for the closure:

func start() {
    for index in 1...3 {
        let i = index
        delay(3.0 * i) {
            print(i)
        }
    }
}

I am not seeing that behaviour though with Xcode 7.3 & Swift 2.2 – the values printed are 1, 2, 3 with your version of the delay function. Are you perhaps using a very old version of Swift? This blog post actually covers the Swift for loop behaviour with value capture.

As noted in the other answer, multiplying the index with 3.0 accomplishes the 3,6,9 second delays.

mz2
  • 4,672
  • 1
  • 27
  • 47
0

If you're looking for a more sophisticated approach, have a look at the types DelayManager and LoopManager here.

They enable straightforward loop syntax like this:

let loopId = LoopManager.shared.with(interval: 0.5, alternating: { [weak self] in
        self?.alpha = 1
    }, and: { [weak self] in
        self?.alpha = 0.2
    })

You can also cancel loops:

LoopManager.shared.stop(withUniqueId: loopId)
Firo
  • 15,448
  • 3
  • 54
  • 74
fredpi
  • 8,414
  • 5
  • 41
  • 61