How to keep the NSTimer always work evenly - ios

Now I am creating a metronome program. I use a NSTimer to bring the metronome into play. Of course The Timer works repeatedly. But I find out in two situation that the timer works not accruately.
When just start the NSTimer, the first two beat sometimes goes too closely. After then, the beat goes evenly.
When the app goes backgound I make the Timer work continuely by:
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
but sometimes the unevenly beat also happens at the time when entering or coming back from the background status.
So I want to know how to keep the Timer always work evenly, no matter which situation it is in. Thks!

When setting up a timer firing at a certain time, the system implicitly sets an allowed "leeway" which is a short delay within the timer may actually fire.
This is due to "Timer Coalescing" - a system feature - which groups events happening roughly at the same time together and fire them at the exact same time. The reason is to reduce CPU cycles and extend the idle time of the CPU to save power.
If the timer interval is small (milli seconds to seconds) this "leeway" is in the range of 10% of the timer interval.
You can explicitly retrieve and set the current maximum allowed leeway value with the methods
-tolerance
-setTolerance:
See also:
NSTimer
Timing Accuracy

Related

CMClock Swift Example

I have two iOS devices physically separate from each other. I need them to perform a task at exactly the top of every minute and bottom of every minute (so every 30 seconds) and stay synchronized.
My initial approach was to calculate the time until the top of the next minute and set a timer until that time and then start my 30 second timer.
The problem was that the 30 second timer would drift and eventually be out of sync.
I discovered an Apple API called CMClock. I could not find an example but was wondering if anyone has used this API and if so could provide an example of how to keep two devices synchronized like I described?

How to keep a timer counting when app reach background

I prepared a CountDown timer for Pomodoro technique. I would like to know how don't pause the app when it reach a background. I have a method which update UILabel from 20min to 0 by 1sec. When Timer reach 0 it should play the sound and vibrate device. All works fine when app is launched in foreground, but how to do it at background? Is it possible to track timer change when app is in background mode?
BR
iMat
The short answer is no. A timer on a VC will not continue to run when the app is in the background because it goes into suspended mode.
You could schedule a local notification to fire when the app is in the background, but as far as updating the UI label, you'll have to update that when the user comes back into the app.
Invalidate the timer when the app goes to background. Store the remaining time remainingTime and current time backgroundTime. (You can get the current time using Date())
Compare the current time backToForegroundTime when the app comes back with backgroundTime. Subtract them to get the time elapsed timeElapsed.
If timeElapsed is less than the remainingTime, subtract that amount from remainingTime and create the timer again with the new duration.
You can use my approach from this gist. Just create repeating timer and update what ever you want in repeating block, and handle timer finishing in other block on main queue or background queue!
Glad to help with questions!
Apple has defined a specific set of tasks, an app can perform when in background.
Running a timer, unfortunately, is not one of them.
Read Background Execution section of app programming guide for more details.
Most apps, intending to continue to execute code in background, implement one of the allowed long running background modes, even if it is not required for your apps actual functionality, and use them to execute their code.
But be ware, you will be doing something apple specifically asks you not to do. This could result in app store rejection if found.

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.

iOS UIWebView Javascript Timers

If a page loaded into a UIWebView contains a Javascript setInterval() call, what is the behavior of that timer when the phone goes sleep?
Is there any point in time when all timers are stopped?
Will the timers be restarted when the phone is woken up? If so, does the timer start at where it was paused, or started from 0?
WebKit internal timer management is a little peculiar in general, and in particular in iOS. They are registered in NSDefaultRunLoopMode mode, so for example, when scrolling in UI, Javascript events do not fire, but they are not aggregated either, like with regular timers (NSTimer).
To answer your question, when the application process is suspended, the timers are also suspended, so they will not fire while the process remains suspended. Once the process is resumed for whatever reason (user opened the app, background fetch, etc.), the timers will resume their run, and will resume to the relative point of when the last tick was supposed to be.
So if you set a timer for every 10 seconds, and close the app at t+1 seconds, then open it again at t+35 seconds, the timer will fire after 5 seconds; you would not hear retroactively the t+10, t+20 and t+30 seconds ticks.
Note: This is the in-process model based timer management of UIWebView /WebKitLegacy/; I am not quite experienced with how WKWebView /WebKit2/ handles them.

what is the best way to update a timer UI

My app draws a timer (with detail to .1 seconds), for which I am currently using a NSTime which fires every .1 seconds. This feels like an absolutely terrible idea, but I'm not sure how else to do it. I don't really care about the .1 seconds updating always, but I would like it to update more than once per second. Is there a good way to do this?
NSTimer doesn't strike me as a bad approach. NSTimer is generally a very regular way to keep track of time (indeed it was used for animation timing before CADisplayLink came along). Unless you are seeing unacceptable performance of your timer display updating, I would stick with this approach.
If you are having issues with delays and inaccurate time readings, you could store the start time in NSDate, and continue to use the NSTimer but only to update the display. On each timer event firing, you then update the display by finding the NSTimeInterval from the start time to now. This way even if there is a performance issue, at least the time being display should remain accurate at the time of display.

Resources