10

I have an NSTimer that I init with this code:

testTimer = [[NSTimer alloc] initWithFireDate:[new objectAtIndex:0] interval:0.0 target:self selector:@selector(works:) userInfo:nil repeats:NO];

[new objectAtIndex:0] is an NSDate in the past.

When I start up the app, the timer is getting created, with a fireDate of immediately (since the date is in the past), however it never calls my works method. (-(void)works:(id)sender )

Anybody know why this is happening?

2
  • whether it is wrong to use iphone tag in this question?
    – Aravindhan
    Commented Jul 19, 2011 at 18:35
  • 1
    Matt, you can use the [osx] tag to help fend off the hordes of iOS retaggers. :)
    – jscs
    Commented Jul 19, 2011 at 20:18

3 Answers 3

18

You will have to add it to the current run loop if you use initWith.. method to create the timer object.

NSRunLoop * theRunLoop = [NSRunLoop currentRunLoop];
[theRunLoop addTimer:testTimer forMode:NSDefaultRunLoopMode];

Or if you would like it set up for you, use the scheduled... methods to create your timer.

3
  • 4
    @Matt: it should be noted that using alloc/init means that you own the timer and need to manage its memory, whereas the scheduledTimer... methods return a timer that you do not own. It is retained by the run loop in either case.
    – jscs
    Commented Jul 19, 2011 at 19:53
  • 1
    @Josh They are good tips. @Matt To be a bit specific about run loop retaining the timer, it happens when you use addTimer:forMode: method. Like mentioned, scheduledTimer... methods do that for you so as a result, the run loop retains the timer. When you invalidate the timer, the run loop releases the timer. Commented Jul 19, 2011 at 20:11
  • 1
    You're right, Deepak, I should have made it clearer that addTimer:... is what causes the run loop to retain the timer. Thanks.
    – jscs
    Commented Jul 19, 2011 at 20:16
15

I just recently had an issue with NSTimer. In my case I didn't realize that the method scheduledTimerWithTimeInterval is not multi thread safe. Once I moved the timer to the main thread it started working.

2
  • 1
    How, may I ask, did you do that? I'm having an issue with it firing seemingly randomly.
    – ari gold
    Commented Dec 9, 2012 at 3:53
  • 5
    try wrapping your nstimer in this: dispatch_async(dispatch_get_main_queue(), ^{ });
    – Dobler
    Commented Dec 25, 2012 at 22:08
3

I think I had the same problem as Dobler, but my solution was different.

The problem was that the timer was being created and scheduled in a GCD thread in a block within a

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{})

call (actually nested deep, so it wasn't obvious that this was the case).

Using NSTimer's scheduledTimerWithTimeInterval:... placed the timer into an invalid run loop.

The fix was to change to

timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(...) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

Not the answer you're looking for? Browse other questions tagged or ask your own question.