Creating repeating and non-repeating timers

Let do a quick run through of the basic operation of the NSTimer object. Timers are generally divided into one of two buckets, repeating and non-repeating. In either case, a timer event is fired after a specified amount of time has elapsed. As the name implies, once the repeating timer fires, it is rescheduled to fire again at the specified interval – this process is repeated until the timer is invalidated.

Repeating NSTimer

The code below shows how to create a repeating timer, which fires ever 3 seconds. The method updateActivityIndicator will be called on each timer event.

// Define the timer object
NSTimer *timer;
 
...
 
// Create the timer object
timer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self 
   selector:@selector(updateActivityIndicator:) userInfo:nil repeats:YES];

Below is a simple test to verify the method is called as expected:

- (void) updateActivityIndicator:(NSTimer *)incomingTimer
{
  NSLog(@"Inside updateActivityIndicator method");
}

To stop the timer, simply call the invalidate method. This will stop the timer and release the object.

[timer invalidate];

Non-Repeating NSTimer

The same method shown above is called to create a non-repeating timer, however the value for the repeats method should be set to NO.

timer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self 
   selector:@selector(updateActivityIndicator:) userInfo:nil repeats:NO];

In this case, after the timer fires, the object will be invalidated with no further code required on your part.

Passing userInfo into an NSTimer Object

You can pass an object to go along for the ride with the timer. For example, below I create a string object and pass it in the userInfo parameter.

NSString *str = @"Timer event has fired";
 
timer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self 
   selector:@selector(updateActivityIndicator:) userInfo:str repeats:YES];

Here is how you can access the userInfo data:

- (void) updateActivityIndicator:(NSTimer *)incomingTimer
{
  if ([incomingTimer userInfo] != nil)
    NSLog(@"userInfo: %@", [incomingTimer userInfo]);
}

If you created a userInfo object, the object will need to be released when the timer is invalidated.

  1. Are you sure that the userInfo Object will be released if the timer gets invalidated? Normally you hold a reference of the timer somewhere so that you can invalidate it later. Invalidate removes only the timer from the run loop AFAIK.

    • Good call, the docs state, “The object you specify is retained by the timer and released when the timer is invalidated.” I didn’t read that close enough. I’ve updated the post…

  2. So, if you add a block to the userInfo dictionary, you could execute it in the timer callback, right?

Comments are closed.