I have a timer in my application that triggers a certain event:
myTimer = NSTimer.scheduledTimerWithTimeInterval(10, target: self,
selector: "searchForDrivers:", userInfo:nil, repeats: true)
The first time the timer is triggered, it has a delay of 10 ms. I don’t want the delay on the first timer trigger, but I'd like the second trigger to be delayed by 10 ms. How can I achieve this?
First schedule the timer as you've done.
timer = NSTimer.scheduledTimerWithTimeInterval(
10.0, target: self,
selector: "searchForDrivers:",
userInfo: nil,
repeats: true
)
Then, immediately afterwards, fire timer.
timer.fire()
According to the documentation,
You can use this method to fire a repeating timer without interrupting its regular firing schedule. If the timer is non-repeating, it is automatically invalidated after firing, even if its scheduled fire date has not arrived.
See the NSTimer Class Reference for more information.
One more way to do that is you can use two timers for that like:
var myTimer = NSTimer()
var secondTimer = NSTimer()
After that you can set two timers this way:
myTimer = NSTimer.scheduledTimerWithTimeInterval(0, target: self,
selector: "searchForTRuckDrivers", userInfo:nil, repeats: false)
secondTimer = NSTimer.scheduledTimerWithTimeInterval(10, target: self,
selector: "searchForTRuckDrivers", userInfo:nil, repeats: true)
You can set first timer with delay 0 which will not repeat again while set another timer with delay 10 and it will repeat again and again.
After that in method you can invalidate first timer this way:
func searchForTRuckDrivers() {
if myTimer.valid {
myTimer.invalidate()
}
}
This will remove first timer but second timer will call this method with delay.
Hope it will help.
Related
I have a Timer that fires every 1.0 seconds. Every time it fires, a TimeInterval variable gets set to Date.timeSinceReferenceDate, and when I pause the timer, another TimeInterval variable also gets set to Date.timeSinceReferenceDate and the timer is invalidated.
When I press the start button again, I want it to resume from where it left off (i.e. if you paused 0.5 seconds before it fired again, it should take 0.5 seconds for it to fire when you resume, not the 1.0 it currently does).
Here's how my code looks:
if (elapsedTime - beginTime) < 1.0 {
leftoverTime = elapsedTime - beginTime
timer = Timer.scheduledTimer(timeInterval: leftoverTime, target: self, selector: #selector(decreaseTime), userInfo: nil, repeats: false)
let fireDate = Date().addingTimeInterval(leftoverTime)
timer = Timer.init(fireAt: fireDate, interval: 1.0, target: self, selector: #selector(decreaseTime), userInfo: nil, repeats: true)
}
I imagine I need to do something with a Run Loop, but isn't there a way to just do a scheduled timer with a fire date? If I do the fire() method, it naturally only runs once and doesn't loop.
Hope someone can shine some light on this.
Thank you.
Edit
I have a UIViewPropertyAnimator
var animator: UIViewPropertyAnimator? = nil
When I start the timer, I first check if it's nil
animator == nil {
animator = UIViewPropertyAnimator(duration: TimeInterval(timeSec), curve: .linear) {
self.view.layoutIfNeeded()
}
}
And then the timer starts initially
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(decreaseTime), userInfo: nil, repeats: true)
In the method for decreasing time, I change the constraints and start the animation
self.timeTrailing.constant = screenSize / 2
self.timeLeading.constant = screenSize / 2
animator?.startAnimation()
At this point it's all good, but when I then hit the pause button and pause the animation (and invalidating the timer), resuming them means they're no longer in sync. I imagine it's because you won't hit an interval of exactly 0.1 when you press it, but rather 0.03, 0.07 etc.
animator?.pauseAnimation()
timer?.invalidate()
How do I ensure that they're always synced up, no matter when and how many times you pause it before it's finished?
i want to display values 1-10 repeatedly in UILable with animation user should be able to see the fluctuation of the values slowly how can i achieve this functionality ?
You can use :
var timer : NSTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "change_label", userInfo: nil, repeats: true)
func change_label()
{
count = count+1
label.text = String(format: "%d",count)
}
I made a practice project in Swift to learn how NSTimer works. There is one button to start the timer and one button to invalidate it. It works fine when I tap each button once. However, when I tap the start timer button multiple times, I am no longer able to invalidate it.
Here is my code:
class ViewController: UIViewController {
var counter = 0
var timer = NSTimer()
#IBOutlet weak var label: UILabel!
#IBAction func startTimerButtonTapped(sender: UIButton) {
timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}
#IBAction func cancelTimerButtonTapped(sender: UIButton) {
timer.invalidate()
}
func update() {
++counter
label.text = "\(counter)"
}
}
I have seen these questions but I wasn't able to glean an answer to my question from them (many are old Obj-C pre-ARC days and others are different issues):
NSTimer() - timer.invalidate not working on a simple stopwatch?
Using an NSTimer in Swift
NSTimer doesn't stop
Unable to invalidate (Stop) NSTimer
NSTimer doesn't stop with invalidate
Can't invalidate, stop countdown NSTimer - Objective C
IOS: stop a NSTimer
You can add timer.invalidate() before starting a new timer in startTimerButtonTapped if you want to reset the timer each time the "start" button is tapped:
#IBAction func startTimerButtonTapped(sender: UIButton) {
timer.invalidate()
timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}
I was going to update with an explanation but #jcaron already did it in the comment, so I'm just quoting his text, no need to change it:
Every time you tap on the "Start Timer" button, you create a new timer, while leaving the previous one running, but with no reference to it (since you've overwritten timer with the new timer you just created). You need to invalidate the previous one before you create the new one.
I would like to suggest you to set timer to nil when press on cancel button.
And don't forget to set counter =0
When invalidating the Timer.
I'm writing a music player using Swift, but when I'm tried to auto scroll the lyric, I found something weird.
I use a NSTimer to trigger the scroll:
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updateTime", userInfo: nil, repeats: true)
func upadate is:
let offset = lyricScrollView.contentOffset
lyricScrollView.setContentOffset(CGPoint(x: offset.x, y: offset.y + 25), animated: true)
but when I change the time interval to 0.1 like this:
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "updateTime", userInfo: nil, repeats: true)
I found that my scrollview doesn't scroll 10x faster than before, instead, it scrolls a little every 0.1 seconds, not 25 points every 0.1 seconds. If I set animated to false, the problem is gone.
Could someone tell me why this happens?
I need a cycle of 5 times of 2.5 seconds in a single cycle, however, that the pressure of a button bait from single cycle without interrupting the scheduling.
I use method fire (with pressed button) for stoping a repeating timer without interrupting its regular firing schedule, but I don't know, subsequent cycles are shorter than the defined 2.5 seconds:
.......
#IBAction func buttonZeroPressed(sender: AnyObject) {
timer.fire()
++addWin
}
......
timer = NSTimer.scheduledTimerWithTimeInterval(2.5, target: self,
selector: Selector("levelOne"), userInfo:nil,repeats: true)
......
func levelOne() {
level = 1
count++
changePhoto()
if (count >= 5) {
timer.invalidate()
}
}
After the 3 pressed button, the timer seems to be 2.5 seconds, and I do not understand why!
The fire() method is how you start a timer that's been created but not scheduled. You want to use invalidate() to stop the timer.
#IBAction func buttonZeroPressed(sender: AnyObject) {
timer.invalidate()
++addWin
}
Your timer will start immediately since you call scheduledTimerWith.... If you wanted to create a timer without starting, you would use:
timer = NSTimer(timeInterval: 2.5, target: self, selector: Selector("levelOne"), userInfo:nil,repeats: true)