Performing Tasks After a Delay

With Core Foundation, you can invoke a selector in an object after a given period of time, using the performSelector:withObject:afterDelay: method of the NSObject class. Here is an example:

- (void) printString:(NSString *)paramString{

  NSLog(@"%@", paramString);

}

- (BOOL)              application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

  @selector(performSelector:withObject:afterDelay:)

  [self performSelector:@selector(printString:)
             withObject:@"Grand Central Dispatch"
             afterDelay:3.0];

  // Override point for customization after application launch.
  [self.window makeKeyAndVisible];
  return YES;
}

In this example we are asking the runtime to call the printString: method after 3 seconds of delay. We can do the same thing in GCD using the dispatch_after and dispatch_after_f functions, each of which is described here:

dispatch_after

Dispatches a block object to a dispatch queue after a given period of time, specified in nanoseconds. These are the parameters that this function requires:

dispatch_after_f

Dispatches a C function to GCD for execution after a given period of time, specified in nanoseconds. This function accepts four parameters:

Delay in nanoseconds

The number of nanoseconds GCD has to wait on a given dispatch queue (specified by the second parameter) before it executes the given function (specified by the fourth parameter).

Dispatch queue

The dispatch queue on which the C function (specified by the fourth parameter) has to be executed after the given delay (specified by the first parameter).

Context

The memory address of a value in the heap to be passed to the C function (for an example, see Performing UI-Related Tasks).

C function

The address of the C function that has to be executed after a certain period of time (specified by the first parameter) on the given dispatch queue (specified by the second parameter).

Note

Although the delays are in nanoseconds, it is up to iOS to decide the granularity of dispatch delay, and this delay might not be as precise as what you hope when you specify a value in nanoseconds.

Let’s have a look at an example for dispatch_after first:

double delayInSeconds = 2.0;

dispatch_time_t delayInNanoSeconds =
  dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

dispatch_queue_t concurrentQueue =
  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_after(delayInNanoSeconds, concurrentQueue, ^(void){
  /* Perform your operations here */
});

As you can see, the nanoseconds delay parameter for both the dispatch_after and dispatch_after_f functions has to be of type dispatch_time_t, which is an abstract representation of absolute time. To get the value for this parameter, you can use the dispatch_time function as demonstrated in this sample code. Here are the parameters that you can pass to the dispatch_time function:

Base time

If this value was denoted with B and the delta parameter was denoted with D, the resulting time from this function would be equal to B+D. You can set this parameter’s value to DISPATCH_TIME_NOW to denote now as the base time and then specify the delta from now using the delta parameter.

Delta to add to base time

This parameter is the nanoseconds that will get added to the base time parameter to create the result of this function.

For example, to denote a time 3 seconds from now, you could write your code like so:

dispatch_time_t delay =
dispatch_time(DISPATCH_TIME_NOW, 3.0f * NSEC_PER_SEC);

Or to denote half a second from now:

dispatch_time_t delay =
dispatch_time(DISPATCH_TIME_NOW, (1.0 / 2.0f) * NSEC_PER_SEC);

Now let’s have a look at how we can use the dispatch_after_f function:

void processSomething(void *paramContext){

  /* Do your processing here */
  NSLog(@"Processing...");

}

- (BOOL)              application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

  double delayInSeconds = 2.0;

  dispatch_time_t delayInNanoSeconds =
    dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

  dispatch_queue_t concurrentQueue =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  dispatch_after_f(delayInNanoSeconds,
                    concurrentQueue,
                   NULL,
                   processSomething);

  // Override point for customization after application launch.
  [self.window makeKeyAndVisible];
  return YES;
}