Hi, I need help. I’ve been looking for an answer for days, and this community has answered my questions best.
In the picture is the overall logic that I want to recreate.
Right now I’m struggling with two major points, the loop and the delay, but I’d like to focus on the former first, as it seems like a simpler problem to solve.
(I have a feeling the solution to the delay problem will have to involve custom classes or something)
If I create an infinite loop, how can I make the end condition to be the the tapping of a button?
I don’t think a loop is the best way to handle something like this.
Instead, something like this would, I think, be better:
(Note: This assumes a view with a single UIButton
for both starting and stopping the timer.)
import UIKit
class ViewController: UIViewController {
@IBOutlet var button: UIButton!
var timer = Timer()
var delay = 0.0
var inLoop = false
var loopCounter = 0
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func buttonTapped(_ sender: UIButton) {
if inLoop {
inLoop = false
stopTimer()
} else {
inLoop = true
startTimer()
}
}
@objc func setDelay(currentTimer: Timer) {
currentTimer.invalidate()
delay = Double.random(in: 0...5)
print("\(loopCounter) : \(delay)")
timer = Timer.scheduledTimer(timeInterval: delay, target: self, selector: #selector(setDelay(currentTimer:)), userInfo: nil, repeats: true)
loopCounter += 1
}
func startTimer() {
print("timer started")
setDelay(currentTimer: timer)
button.setTitle("Stop Timer", for: .normal)
}
func stopTimer() {
timer.invalidate()
print("timer stopped")
button.setTitle("Start Timer", for: .normal)
delay = 0.0
loopCounter = 0
}
}
So in case this isn’t clear, what we’re doing is when the UI’s button is clicked we schedule a Timer
object and set its timeInterval
property to random Double
values. (The initial timeInterval
is 0, which means the timer will fire right away.) When the timer fires off, we invalidate it and create a new one with a new timeInterval
value and do it all over again.
This will continue until you tap the button again to make it stop.
Make sense?
1 Like
thank you. I think this really puts me on the right tracks.
This looks like this loop is based upon the current function being used and is applied before the function.
What I’d like to do is call the function, and then cause a delay AFTER the function based on the Double value returned within it. clear as mud?
For example.
Random function one is called and returns:
“Turn to heading 180 degrees”
where the var currentHeading = 0
delay applied to the NEXT function would be (180 - currentHeading) / 3 + Double.random(1…15)
Random function two is now called, with the above delay.
the delay would be different depending on which function was previously called
Over and over again until button is tapped again to stop it.
Yep, that’s what this does.
Except that I realize in making an edit to the code I accidentally erased a comment that explained how to adapt it for your needs.
Where I have this line:
delay = Double.random(in: 0...5)
You should replace it with a call to a function that returns a Double, like:
delay = runRandomFunction()
And then runRandomFunction()
would take care of getting a random function, running it and returning a Double value for the new delay amount.
Or if you wanted to do it all inline and you had a property called, say, funcArray
that contained your list of functions that return a Double
, you could do something like:
delay = funcArray.randomElement()!()
thanks! I’m going to try and make it work from all the stuff you’ve given me, it’s amazing. Are you okay if I message you again in case I get stuck?