2

ブロックについてはよくわかりません。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
4

3 に答える 3

5

したがって、ブロックを起動するタイマーの場合は、ディスパッチ ソースを使用します。ADC Web サイトには、アプリで 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 に答える