Reputation: 1239
I previously had a single NSTimer
which is working fine. I have added another NSTimer
to my runloop as now I need to call two functions repeatedly after a delay. Both functions have a different delay. My code is given below.
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:500
target:self
selector:@selector(Func1)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
[self.runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10000]];
//Second timer start here.its not working.The function 'func2' is not getting called
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:60
target:self
selector:@selector(Func2)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
[self.runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10000]];
The first NSTimer
is still working but the second NSTimer
doesn't work.
Upvotes: 0
Views: 772
Reputation: 330
Declare a second property for your timers is not the solution. You just have to invalidate the old timer and allocate the new one on main thread and it will works! try this:
dispatch_async(dispatch_get_main_queue(), ^{
_timer = [NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(function:)
userInfo:nil
repeats:YES];
[_timer fire];
});
Upvotes: 0
Reputation: 438232
While it's not good that you're overwriting your properties (it doesn't affect the timers' ability to run, individually, but it just means that you're discarding your reference to the first timer when you set the second timer, and thus you lose the ability to invalidate
the first timer, should you ever need to do that), the key problem is that you're calling runUntilDate
. There's no need to do that and the first runUntilDate
is preventing the creation of the second timer from taking place as viewDidLoad
will not proceed beyond the first runUntilDate
call.
So remove both calls to runUntilDate
and both timers will work fine. Use different properties to save the reference to the two timers if you want to keep a reference to both so that you can individually invalidate
them if and when you no longer need them. (And it's important that you invalidate
them when you no longer need them because they maintain a strong reference to self
, which means that you have a "strong reference cycle".)
You could simplify the code sample:
NSDate *date = [NSDate date];
self.timer1 = [[NSTimer alloc] initWithFireDate:date
interval:500
target:self
selector:@selector(method1:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer1 forMode:NSRunLoopCommonModes];
self.timer2 = [[NSTimer alloc] initWithFireDate:date
interval:60
target:self
selector:@selector(method2:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer2 forMode:NSRunLoopCommonModes];
Or, unless you really need NSRunLoopCommonModes
, you could just do:
self.timer1 = [NSTimer scheduledTimerWithTimeInterval:500
target:self
selector:@selector(method1:)
userInfo:nil
repeats:YES];
self.timer2 = [NSTimer scheduledTimerWithTimeInterval:60
target:self
selector:@selector(method2:)
userInfo:nil
repeats:YES];
And note, I'm using methods with a parameter (hence the colon with the selector):
- (void)method1:(NSTimer *)timer
{
// do whatever
}
- (void)method2:(NSTimer *)timer
{
// do whatever
}
Upvotes: 3
Reputation: 500
Actually the runUntilDate
will cause the app to keep on running the timer and the statements after this will not be executed. Try this:
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:500
target:self
selector:@selector(Func1)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
//Second timer start here.its not working.The function 'func2' is not getting called
self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:60
target:self
selector:@selector(Func2)
userInfo:nil
repeats:YES] ;
self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
Even if you use the same timer
variable for both timers, it will work. But as pointed out in other answers, you lose the ability to invalidate the first timer. Just comment out the runUntilDate
statements in both places.
Upvotes: 0
Reputation: 4658
You have to declare a second property of NSTimer. Currently you are overwriting your first timer when doing this
self.timer = [[NSTimer alloc] initWithFireDate:self.now
interval:60
target:self
selector:@selector(Func2)
userInfo:nil
repeats:YES] ;
Declare timer2 in your interface analogues to your timer declaration and the use self.timer2 to store the second timer.
Upvotes: 2