Reputation: 87
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
}
Upvotes: 2
Views: 3576
Reputation: 6383
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...
Upvotes: 0
Reputation: 288
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.
Upvotes: 0
Reputation: 2082
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
}
Upvotes: -1
Reputation: 31645
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)
Upvotes: 0
Reputation: 61
I would suggest using a Timer:
Move the loop to a function
func playSound(for value: Int, in array: [Int]) {
if array.contains(value) {
playSound()
}
}
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
})
Upvotes: 2