NSTimer timerWithTimeInterval: not working
I've created a test application with timer before implementing it in my project.
It was the first time I'm using timer.
But the issue is when I implemented timer using [NSTimer timerWithTimeInterval: target: selector: userInfo: repeats: ];
, it is not working.
Here is my code,
Interface:
@interface uialertViewController : UIViewController
{
NSTimer *timer;
}
-(void)displayAlert;
-(void)hideandview;
@end
Implementation:
@implementation uialertViewController
- (void)viewDidLoad {
[self displayAlert];
[super viewDidLoad];
}
-(void)displayAlert{
timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(hideandview) userInfo:nil repeats:NO];
alert = [[UIAlertView alloc] initWithTitle:@"testing" message:@"hi hi hi" delegate:nil cancelButtonTitle:@"continue" otherButtonTitles:nil];
[alert show];
[alert release];
alert = nil;
}
-(void)hideandview{
NSLog(@"triggered");
[alert dismissWithClickedButtonIndex:0 animated:YES];
[alert release];
[self displayAlert];
}
@end
Then I Changed [NSTimer timerWithTimeInterval: target: selector: userInfo: repeats: ];
with [NSTimer scheduledTimerWithTimeInterval: target: selector:userInfo: repeats: ];
, It is working. What was the issue with timerWithTimeInterval:
? Am I mising anything in my first implementation ? Thanks in advance.
Solution 1:
scheduledTimerWithTimeInterval:invocation:repeats:
and scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
create timers that get automatically added to an NSRunLoop
, meaning that you don't have to add them yourself. Having them added to an NSRunLoop
is what causes them to fire.
With timerWithTimeInterval:invocation:repeats:
and timerWithTimeInterval:target:selector:userInfo:repeats:
, you have to add the timer to a run loop manually, with code like this:
[[NSRunLoop mainRunLoop] addTimer:repeatingTimer forMode:NSDefaultRunLoopMode];
Other answers on here suggest that you need to call fire
yourself. You don't - it will be called as soon as the timer has been put on a run loop.
Solution 2:
Also one may want to make sure to add timer on the main thread.
assert(Thread.isMainThread)
let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(YourSelector), userInfo: nil, repeats: true)
Solution 3:
As a previous answer noted schedule on the main thread, but rather than using assert, put it on the main thread:
@objc func update() {
...
}
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
}
And if async is not desired, try this:
let schedule = {
self.timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
}
if Thread.isMainThread {
schedule()
}
else {
DispatchQueue.main.sync {
schedule()
}
}