不知道很多关于积木的事情。您将如何使用NSTimer
模仿重复的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
答案 0 :(得分:5)
因此,对于您想要触发一个块的计时器,您需要一个调度源。 ADC网站上有一个很好的例子,我在我的应用程序中多次使用NSTimer代替:
答案 1 :(得分:4)
您也可以通过将NSTimer
设置为fireDate
来“暂停”一个香草[NSDate distantFuture]
。当您的应用程序返回到前台时,您可以简单地恢复正常的计划。
答案 2 :(得分:3)
我对块和后台任务我不太了解,但我会想到一种不同的技术来“暂停”你的计时器:
我建议覆盖applicationDidEnterBackground
并存储计时器的剩余时间(基于NSTimer's
fireDate
),然后当应用返回前台时applicationWillEnterForeground
根据您之前保存的时间戳触发,失效并重新计算您的计时器。
我没有测试过这个解决方案,但似乎它应该正常工作
希望这会有所帮助:)