Scheduled NSTimer's selector called with delay in iOS - ios

I have an NSTimer that should be running all the time the app is active. It is intended to show a countdown that depends on certain user's actions. I fire this timer this way:
self.timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(notifyTimerTick:)
userInfo:nil
repeats:YES];
Then, in the method notifyTimerTick:, I update the countdown label I show to users and, if the countdown is over, I invalidate the timer, I look for a new countdown, and I fire the timer again.
I'm not having troubles being the UI blocked doing this way, but on the other hand, I've found that sometimes the notifyTimerTick: selector call is significantly delayed: I have a view that takes a couple of seconds to be completely loaded, and I've seen that timer's selector is not called until the corresponding view controller's viewDidLoad delegate method is called.
I've read several posts dealing with timers blocking the UI, but I'm not sure how to deal with a timer getting blocked by the UI... what the best way to handle this should be?
Thanks in advance

You need to use a different run loop mode.
When you use the ScheduledtimerWithTimeInterval class method, the timer is scheduled on the current run loop.
Instead do something like this:
NSTimer *labelTick = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:labelTick forMode:NSRunLoopCommonModes];

Related

NStimer stopped at middle

I am doing one application.In that,i am calling one method for every 10 seconds using the timer.But after sometime that method is not calling. So,may i know the reason for why timer is stopped.
If there is a ScrollView scrolling, the timer in NSDefaultRunLoopMode will be stopped.
You can use this to fix it:
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
If you are checking Timer in Foreground and background, Timer will work continuously in foreground, But in background it will work only 10 mins, After that timer will not work.

Watch OS2 NSTimer problems

I'm working on an App where I need to start a timer (using NSTimer) when the Watch is activated. With the Timer I asks some information to the iPhone (about every 1 seconds and maximum for 5 seconds). I'm using this to start the timer
timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(myfunction) userInfo:nil repeats:NO];
In the "myfunction" function, I restart the timer for the next time.
- (void) myfunction
{
//Here I update a label text
// [...]
[timer invalidate];
timer = nil;
counter++;
if(counter<5)
{
timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(myfunction) userInfo:nil repeats:NO];
}
}
My problem is that in the simulator all works fine but in a real watch (Watch-OS2 GM) the timer sometimes doesn't start or sometimes it starts but only for one time and after seems freeze! I see this because i Update a label in the watch at every elapsed period that shows a counter and I'm sure all is initialized in the "will activate" function. I don't understand why. Someone with the same issue?
From documentation
Use your interface controller’s init and awakeWithContext: methods to
load any required data, set the values for any interface objects, and
prepare your interface to be displayed. Do not use the willActivate to
initialize your interface controller. The willActivate method is
called shortly before your interface is displayed onscreen, so you
should use that method only to make last-minute changes. For example,
you might also use that method to start animations or start other
tasks that should only happen while your interface is onscreen.
So, what method did you use to instantiate timer?
make sure you use willActivate method and also use the didDeactivate method to clean up your interface and put it into a quiescent state. For example, use this method to invalidate timers and stop animations.
Hope this helps
My problem is solved with Watch OS 2.1. The problem was related to a quickly movement of the wrist: with the latest update of WatchOS all the timer are correctly restore after a quick move and all works fine

Background timer IOS

In my app the user can planify an event, thanks to a timer.
I want this timer to work even if the app is in background.
How can I do that ?!
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerFired) userInfo:nil repeats:YES];
If you want to trigger some actions after a period even if the app is in background Local notifications can help you.
Refer https://developer.apple.com/library/ios/DOCUMENTATION/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction.html
And there is tutorial here http://www.appcoda.com/ios-programming-local-notification-tutorial/
Note : NSTimer will stop on app entering background

Make the ios app working in background

I'm using the pitch detection code from demetri miller demetri miller pitch detection in my application. I want the microphone to work in background and give a UILocalNotification on a particular pitch.
How to make the application run in background.
Currently when the app is in background is there way to make it work fully.
Use the NSTimer when app is going from foreground to background start NSTimer and every one second your timer method will call and you can check the application state. you can execute every thing fine.
NSTimer *timerBackground = [NSTimer timerWithTimeInterval:1.0
target:self
selector:#selector(YourMethod:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timerBackground forMode:NSDefaultRunLoopMode];

how to prevent an NSTimer to be delayed or interrupted by user interface actions in iOS 5

How can I prevent a NSTimer from being delayed by the user scrolling a table?
I found the answer:
I had a timer that repeated about 8 or 9 times with intervals of 0.4 to 0.8 seconds. I don't need much precision, but if the user scrolls a table the timer would stop working until the table finished scrolling (this could be a few seconds wait!). I thought I needed background threads, but timers on background threads were somewhat complicated to implement.
The answer to my problem was very very simple and easy. I just need to add a line after invoking the timer:
//////////// start the timer
self.playingTimer = [NSTimer scheduledTimerWithTimeInterval:tempo target:self selector:#selector(playSoundFromArray:) userInfo:nil repeats:YES];
//////////// the magic line:
[[NSRunLoop currentRunLoop] addTimer:self.playingTimer forMode:UITrackingRunLoopMode];
Now I can scroll the table as much as I want and my timers work OK!!!
Now I need to study a little more NSRunLoop...
You should add your timer for NSDefaultRunLoopMode mode. UITrackingRunLoopMode is used by tracking UI actions(in your case scrolling).

Resources