views:

378

answers:

2

Basically, I have an array of buttons I want to iterate and highlight (among other things) one after another, with a delay in-between. Seems like an easy task, but I can't seem to manage to get it to work cleanly while still being responsive.

I started out with this:

for MyButton *button in buttons {
    [button highlight];
    [button doStuff];
    usleep(800000); // Wait 800 milliseconds.
}

But it is unresponsive, so I tried using the run loop instead.

void delayWithRunLoop(NSTimeInterval interval)
{
    NSDate *date = [NSDate dateWithTimeIntervalSinceNow:interval];
    [[NSRunLoop currentRunLoop] runUntilDate:date];
}

for MyButton *button in buttons {
    [button highlight];
    [button doStuff];
    delayWithRunLoop(0.8); // Wait 800 milliseconds.
}

However, it is also unresponsive.

Is there any reasonable way to do this? It seems cumbersome to use threads or NSTimers.

+2  A: 

NSTimer will be perfect for this task.

The timer's action will fire ever x seconds, where x is what you specify.

The salient point is that this doesn't block the thread it runs on. As Peter said in the comments for this answer, I was incorrect in saying the timer waits on a separate thread. See the link in the comment for details.

Jasarien
NSTimer does not use a separate thread. It uses the run loop on the current thread. See http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Timers/Articles/timerConcepts.html and http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/ .
Peter Hosey
+1  A: 

Nevermind, Jasarien was right, NSTimer is perfectly suitable.

- (void)tapButtons:(NSArray *)buttons
{
    const NSTimeInterval waitInterval = 0.5; // Wait 500 milliseconds between each button.
    NSTimeInterval nextInterval = waitInterval;
    for (MyButton *button in buttons) {
        [NSTimer scheduledTimerWithTimeInterval:nextInterval
                                         target:self
                                       selector:@selector(tapButtonForTimer:)
                                       userInfo:button
                                        repeats:NO];
        nextInterval += waitInterval;
    }
}

- (void)tapButtonForTimer:(NSTimer *)timer
{
    MyButton *button = [timer userInfo];
    [button highlight];
    [button doStuff];
}
Michael