I have an array that contains time values in milliseconds e.g.:
let executionTimes = [0, 1500, 3500, 4700]
On top there is a function that simply does anything - for now - print some text:
func printHello() {
print("Hello")
}
What I'd like to do is execute the function after the given periods of time in the array. So printHello() will be executed immediately, then after 1,5 secs, then after another 2 secs and finally after another 1,2 secs before beginning from the start again. For now I want this timing of function calling to continue "forever".
First I tried using NSTimer to solve this, but from what I found out it is not possible to dynamically change the timeInterval of a timer without invalidating it first and this tempers with the given time schedule.
Then I thought using performSelector could solve this:
func executeCustomScheduler(timeIndex: Int) {
let time: Double = executionTimes[timeIndex]
NSLog("Hello")
let nextTimeIndex = timeIndex == (executionTimes.count - 1) ? 0 : timeIndex + 1
self.performSelector(Selector(executeCustomScheduler(nextTimeIndex)), withObject: self, afterDelay: time)
}
This doesn't work at all as the function is being executed without delay at all, and runs into a crash because of the recursive calls I think.
Could anybody please provide any useful hint on this?
Thanks a lot!
There are multiple things wrong here:
Selector(executeCustomScheduler(nextTimeIndex))
creates a selector based on the return value of executing executeCustomScheduler(nextTimeIndex)
one timewithObject: self
- why would you pass self
?performSelector
at all?executionTimes
is not in milliseconds but in seconds, or at least the method expects them to beperformSelector
Solutions:
Selector("executeCustomScheduler:")
is the correct selectornextTimeIndex
is the correct argument to pass alongperformSelector
String
instead of an Int
:/Better solution:
Use dispatch_after
, get rid of those pesky selectors and be typesafe all the way through:
class Obj {
let executionTimes = [0, 1500, 3500, 4700]
func executeCustomScheduler(timeIndex: Int) {
NSLog("Hello")
let time = executionTimes[timeIndex]
let nextTimeIndex = (timeIndex + 1) % executionTimes.count
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(Double(time) / 1000 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
self.executeCustomScheduler(nextTimeIndex)
}
}
}
let obj = Obj()
obj.executeCustomScheduler(0)