2

对积木知之甚少。你会如何去模仿一个重复NSTimerwith dispatch_after()?我的问题是,当应用程序移至后台时,我想“暂停”一个计时器,但子类化NSTimer似乎不起作用。

我尝试了一些似乎有效的方法。我无法判断它的性能影响或是否可以大大优化。欢迎任何意见。

#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
4

3 回答 3

5

因此,对于您想要触发块的计时器,您需要一个调度源。ADC 网站上有一个很好的例子,我在我的应用程序中多次使用它来代替 NSTimer:

http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/GCDWorkQueues/GCDWorkQueues.html%23//apple_ref/doc/uid/TP40008091-CH103-SW2

于 2011-04-25T22:55:32.370 回答
4

您也可以NSTimer通过将 设置为fireDate来简单地“暂停”香草[NSDate distantFuture]。当您的应用程序回到前台时,您可以简单地恢复正常的时间表。

于 2011-01-17T17:51:31.057 回答
3

我自己对块和后台任务不太了解,但我会想到一种不同的技术来“暂停”你的计时器:

我建议覆盖applicationDidEnterBackground并存储计时器的剩余时间(基于NSTimer's fireDate),然后当应用程序返回前台并被applicationWillEnterForeground触发时,根据您之前保存的时间戳使计时器无效并重新计算。

我还没有测试过这个解决方案,但似乎它应该可以工作

希望这可以帮助 :)

于 2011-01-17T17:02:19.580 回答