NSTimer start delay - ios

I have an UIButton that triggers a NSTimer with 1 sec interval, it calls a selector a countdown, this countdown is shown in the screen. We have detected that the NSTimer does not start immediately, it costs one second aprox. to begin. Is there anyway to force NSTimer to start immediately?
Thanks!

NSTimer has a fire method. call it after initialization.
check the documentation here https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/NSTimer_Class/Reference/NSTimer.html#//apple_ref/occ/instm/NSTimer/fire

Related

Get remaining time of Timer in Dart

How to get the remaining time in seconds of Timer from 'dart:async' in Dart?
I have a countdown timer and at some point I want to get the remaining time in seconds. How do I do this in dart?
_endTimer = Timer(Duration(seconds: totalRemainingTimeInSeconds), () {
_end();
});
You cannot get that from a Timer.
What you can do is to start a Stopwatch at the same time as the timer.
If you need to do things along the way, they can check the stopwatch to see the duration so far. To update a countdown timer, I'd probably use a combination of Stopwatch to count time and Timer.periodic to update the UI occasionally, and either have the periodic timer check whether the countdown is over, or have a single Timer to react on timeout.

Why timer invoke its block so quickly sometimes

I create a timer and invoke its block every 5 second. Then I make application to enter background and enter foreground after a while. But it could invoke the block quickly sometimes.
let _ = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { (timer) in
print("--------")
}
When I enter foreground the interval of first printing and second printing may less than a second sometimes. Is time interval invalid in this case?
To understand the behavior, you need to understand how NSTimer and RunLoop works. In simple terms, a RunLoop would check if the Timer should fire, if yes it would notify the Timer to fire the selector, else it won't. Now, since you are on the background, your RunLoop is not checking for events so it won't be able to notify the Timer. But once it goes to foreground, it would see that it would need to notify the Timer even if it passed the fireDate.
TimeLine Diagram:
Let A(5th second) and B(10th second) be timer fire events. Scheduled on a timer Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true)
C is entered background (0 seconds)
D be coming back to foreground (9th second, between A and B).
-----> A ------> B
C--------->D
Explanation:
On C, the RunLoop would be paused. Therefore Event A is not able to be processed until the RunLoop has resumed processing, which is on Event D. Upon Event D, it will see that Event A should fire so it would notify the Timer. After a second, the RunLoop would see that Event B has happened so it would notify the Timer again. This scenario explains why your events are printing in a second's interval. It is just the delayed event handling that makes it seem that it fired earlier, when in reality it was processed late.
Apple Doc:
A timer is not a real-time mechanism. If a timer’s firing time occurs
during a long run loop callout or while the run loop is in a mode that
isn't monitoring the timer, the timer doesn't fire until the next time
the run loop checks the timer. Therefore, the actual time at which a
timer fires can be significantly later.
resources: What is an NSTimer's behavior when the app is backgrounded?, NSRunLoop and Timer Docs
Suggestions:
Stop your timer once app goes background, but store the fireDate. Once coming back to foreground, check if fireDate is past Date(). Then create a new Timer to handle events while on foreground.
When application entered background, the app would be suspended soon, program stopped running. When app switched back to foreground, the buffered/delayed timer event would be fired, then you saw many prints quickly.

How to check if timer is less than some value then to run function?

I wrote this line:
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "showGallery:", userInfo: nil, repeats: false)
So, it runs when my 0.5 seconds are expired. But I want to run those function if there are difference between seconds is less than 0.5.
For example: I touch the screen and do not release it 1 second. Then it do not need to run my func, but if I touched and released quickly, then it must run.
How can I modify my function?
Measure the elapsed time when the press is released and execute the function if the interval is too short. As is, you're going about it wrong with a timer
As #Feldur said, you have to change your approach with the timer. Try to implement something like stopwatch from this question.
Start timer with 1/10 of sec as interval when touch begins. In fire method count how many times timer did fire. If it fired too many times - invalidate timer. When touch ends invalidate timer and check how many times it fired. If it didn't fire enough times - run method you wanted.

Application's run loop slows down when receive/initiate a cellular call

I have a timer that fires a method in every 60ms of interval when the application is in foreground and fires in the same interval even if it is in background.
When I initiate/receive a cellular call, the timer fires the method in every 120ms of interval.I thought it is a problem with the timer, so I tried the following approaches.
Approaches I have tried:
NSTimer in background thread.
NSTimer in main thread.
dispatch_source_timer
while loop with 60ms of sleep. (No timer here)
So even if you use a simple while loop, still there is a delay in firing the method. So to maintain the interval I changed the timer interval to 30ms(for all the approaches) when I receive/initiate a call but the result is same(120 ms).
I will be glad if anyone can suggest an approach.
From the Apple Doc:
If a timer’s firing time occurs during a long callout or while the run loop is in a mode that is not monitoring the timer, the timer does not fire until the next time the run loop checks the timer. Therefore, the actual time at which the timer fires potentially can be a significant period of time after the scheduled firing time
What you should remember about Timer is that when you set it to a time T, you have the assurance that the elapsed time between two ticks is at least of T.

Pause CFTimeInterval Timer?

In my game I have a timer in my update loop that updates a label based upon the interval returned in this line:
elapsedTime = 90 - (CFAbsoluteTimeGetCurrent() - startTime);
Now 90 is the time we tick down from. I set startTime like so:
startTime = CFAbsoluteTimeGetCurrent();
Now what I am aiming to do is "pause" this timer when I go to my pause menu. However I just cannot wrap my head around the logistics of it.
When I pause should I set startTime to 0? If so, what would I do during the resume method?
Basically if the user pauses the game with 85 seconds to go, I want the user to come back from the pause screen with 85 seconds to go still. How would I achieve this?
I got my answer. I just did what I was doing now but I included another timer for the paused screen and I just add it up continually when paused and then I incorporate that timer into my game timer and it worked out.
You could store the amount of time, that passed since the timer started.
With NSDate you can store the startTime of the timer and than use -timeIntervalSinceNow to retrieve the time that passed.

Resources