2

I currently have a loop like this, but I realize that using sleep is not the way to do this. I want it to take 60 seconds to go next iteration in the loop. How might I approach this in a better way? Thanks!

for count in 0...60 {
   if arrayOfOptions.contains(count) {
      // play a sound.     
   }
   sleep(1) // pause the loop for 1 second before next iteration
}
1
  • I've presented an answer below, but I'm unsure if your question might actually be complicating things? Do you simply want to repeat the sound a certain number of times, or is there another purpose to the arrayOfOptions that has to do with the playback? (Do you actually use the values to differentiate sounds for instance?) Commented Apr 23, 2018 at 10:56

5 Answers 5

2

I would suggest using a Timer:

  1. Move the loop to a function

    func playSound(for value: Int, in array: [Int]) {
        if array.contains(value) {
            playSound()
        }
    }
    
  2. Create a timer:

    Timer.scheduledTimer(withTimeInterval: 1.0, 
                         repeats: true) { [weak self] _ in
                             guard let array = self?.array, let index = self?.currentIndex else { return }
                             self?.playSound(for: index, in: array)
                             self?.index = index + 1
                         })
    
Sign up to request clarification or add additional context in comments.

Comments

0

I agree with Ahmad F that recursion is probably the way to go. My example is solution is in the same ballpark, with the difference that I pass the index to avoid having a class-wide variable just for this purpose. (+ some minor stylistical differences).

func playSound(fromIndex index: Int = 0)) {
    guard index < arrayOfOptions.count else { return } // safety first
    if arrayOfOptions.contains(index) {
        // play a sound
    }
    guard index <= 60 else { return }

    Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
        self.playSound(fromIndex: index+1)
    }
}

This would simply be started with playSound()

@PurplePanda If the idea is to run through the entire array, changing the guard statement to guard index < arrayOfOptions.count else { return } would be more sensible. That is also why I have added the initial guard statement, since there is no technical reason to assume the array isn't empty...

It might easily make sense to expand upon this and having the function receive the array as well, but that depends on your specific requirements obviously...

Comments

0

You could achieve thus by following the recursion approach, for instance:

var count = 0
func playSound(delayInSeconds: Int) {
    // here you can do your functionality
    print("\(count): do my thing")

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(delayInSeconds)) {
        if self.count < 61 {
            self.count += 1
            self.playSound(delayInSeconds: delayInSeconds)
        }
    }
}

thus you call it as:

playSound(delayInSeconds: 2)

Comments

0

Here's a function to which delays the execution for the specified amount of time.

//MARK: Delay function

func delay(_ delay:Double, closure:@escaping ()->()) {
    DispatchQueue.main.asyncAfter(
        deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
}

and you use the function like so :

delay(2)  //Specify the amount of time - In your case "1" second
{
      //Put the delayed code here
}

Hope this helps you out.

Comments

-1

Call this function from for loop:-

//MARK: Delay func 
func delay(_ delay:Double, closure:@escaping ()->()) {
    DispatchQueue.main.asyncAfter(
        deadline: DispatchTime.now() + Double(Int64(delay * 
    Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
}

Example :-

for() {
    //your code
    self.delay(2) {

    }
    //Your code
}

2 Comments

This doesn't delay the loop iterations. It just puts a pause before the for loop runs. My goal is to have the loop take sixty seconds to run, but this just delays for two (or any chosen value) seconds then the loop runs at full speed.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // change 2 to desired number of seconds // Your code with delay } This creates the desired "wait" effect in Swift 3 and Swift 4. Try this one

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.