I'm a bit late catching up on feeds, but I came across Brent Simmons' post on Coalescing today and—having solved the same problem in a different way—thought I'd chime in.

Coalescing calls is great for things like data stores that are backed by an archive on disk, because you want every operation to call -synchronize when it's finished (for data integrity), but you also don't want it to be over-called (for performance). In my own use today, coalescing saved 75% of the disk writes in my test harness which, while obviously a contrived case, proved its usefuless immediately.

In my own limited experience, NSTimer or -performSelector:afterDelay: are a code smell1, and their use should be eliminated and replaced with something that is more appropriate to the problem being solved. In unit testing, I use dispatch_group to block tests until the side effects (in this case, delegate calls) have been completed as expected. For call coalescing—since I'm already using GCD for mutexing—I simply add a counter:

// Called on lockQueue, a serial dispatch queue.
- (void)synchronize;
{
    self.syncCount++;

    dispatch_async(lockQueue, ^{
        if (--self.syncCount == 0) {
            // Do your work here.
        }
    });
}

Super simple, and if you're already using dispatch queues for locking, which I highly recommend, all you need to add is a property. For a minor performance boost (avoiding Block_copy) replace dispatch_async with dispatch_async_f and the appropriate glue.


1 Although I can see an argument for their use for UI/animations, more often they're used to try to avoid race conditions that aren't understood or to queue something to run after the main thread's runloop has finished its current iteration2.
2 For which you should be using dispatch_async(dispatch_get_main_queue(), ^{ /* … */}) instead.