iPhone: Using dispatch_after to mimick NSTimer

Posted by Joseph Tura on Stack Overflow See other posts from Stack Overflow or by Joseph Tura
Published on 2011-01-17T15:46:14Z Indexed on 2011/01/17 16:53 UTC
Read the original article Hit count: 257

Don't know a whole lot about blocks. How would you go about mimicking a repeating NSTimer with dispatch_after? My problem is that I want to "pause" a timer when the app moves to the background, but subclassing NSTimer does not seem to work.

I tried something which seems to work. I cannot judge its performance implications or whether it could be greatly optimized. Any input is welcome.

#import "TimerWithPause.h"


@implementation TimerWithPause

@synthesize timeInterval;
@synthesize userInfo;
@synthesize invalid;
@synthesize invocation;

+ (TimerWithPause *)scheduledTimerWithTimeInterval:(NSTimeInterval)aTimeInterval target:(id)aTarget selector:(SEL)aSelector userInfo:(id)aUserInfo repeats:(BOOL)aTimerRepeats {

    TimerWithPause *timer = [[[TimerWithPause alloc] init] autorelease];

    timer.timeInterval  = aTimeInterval;

    NSMethodSignature *signature = [[aTarget class] instanceMethodSignatureForSelector:aSelector];
    NSInvocation *aInvocation = [NSInvocation invocationWithMethodSignature:signature];
    [aInvocation setSelector:aSelector];
    [aInvocation setTarget:aTarget];
    [aInvocation setArgument:&timer atIndex:2];
    timer.invocation = aInvocation;

    timer.userInfo      = aUserInfo;

    if (!aTimerRepeats) {
        timer.invalid = YES;
    }

    [timer fireAfterDelay];

    return timer;
}

- (void)fireAfterDelay {

    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, self.timeInterval * NSEC_PER_SEC);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_after(delay, queue, ^{

    [invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO];

    if (!invalid) {         
        [self fireAfterDelay];
    }
});
}

- (void)invalidate {
    invalid = YES;

    [invocation release];
    invocation = nil;

    [userInfo release];
    userInfo = nil;
}

- (void)dealloc {

    [self invalidate];

    [super dealloc];
}

@end

© Stack Overflow or respective owner

Related posts about objective-c

Related posts about block