値をNSTimer
減らすために3秒間隔で起動するがあります。その値を増やすアクションを実行するとき、その時点から3秒をカウントするようにタイマーを再起動したいと思います。
たとえば、値を増やしてタイマーが1秒で起動する場合、それを変更して、代わりに3秒でタイマーを起動させたいと思います。タイマーを無効にして再度作成できますか?またはsetFireDate:
、現在の日付を使用して3秒の間隔を追加して、それを行うことはできますか?
値をNSTimer
減らすために3秒間隔で起動するがあります。その値を増やすアクションを実行するとき、その時点から3秒をカウントするようにタイマーを再起動したいと思います。
たとえば、値を増やしてタイマーが1秒で起動する場合、それを変更して、代わりに3秒でタイマーを起動させたいと思います。タイマーを無効にして再度作成できますか?またはsetFireDate:
、現在の日付を使用して3秒の間隔を追加して、それを行うことはできますか?
はい、無効にすることができます。そして、それを再度作成します。
次のものも使用できます。
- (void) myTimedTask {
// other stuff this task needs to do
// change the variable varyingDelay to be 1s or 3s or... This can be an instance variable or global that is changed by other parts of your app
// weStillWantTimer is also a similar variable that your app uses to stop this recurring task
if (weStillWantTimer)
[self performSelector:@selector(myTimedTask:) withObject:gameColor afterDelay:varyingDelay];
}
myTimedTaskを呼び出して、定期的なタスクを開始します。開始したら、variingDelayを使用して遅延を変更するか、weStillWantTimerを使用して遅延を停止できます。
少しテストを行いましたが、fireDateのリセットは、タイマーを無効にして再作成するよりも約4倍高速であることがわかりました。まず、メソッドdoNothingを呼び出すタイマーを作成します。
if (!testTimer) {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0
target:self
selector:@selector(doNothing:)
userInfo:nil
repeats:NO];
testTimer = timer;
}
テストコードは次のとおりです。
- (void) testInvalidatingTimer {
for (int n = 0; n < 10000; n++) {
[testTimer invalidate];
testTimer = nil;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0
target:self
selector:@selector(doNothing:)
userInfo:nil
repeats:NO];
testTimer = timer;
}
}
- (void) testResettingTimer {
for (int n = 0; n < 10000; n++) {
if ([testTimer isValid]) {
testTimer.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0];
}
}
}
iPad Airで実行すると、validateTimerの場合は0.198173秒、resettingTimerの場合は0.044207秒になります。パフォーマンスが目標である場合は、fireDateをリセットすることをお勧めします。また、コーディングの労力もかなり少なくなります。
タイマーを無効にして再作成します。ただし、実行ループはタイマーが無効になるまでタイマーを保持してから自動的に解放するため、必要が確実でない限り、タイマー を無効にして解放しないようにしてください。
私の意見では、-performSelectorコードとタイマーコードを混在させると、ターゲットメソッドが複数回実行されるため、それは避けたいと思います。
はい、タイマーの無効化と再作成は機能します。それは本質的にあなたがあなたの価値を増やさないならばあなたがしたいことです:リセットして最初からやり直してください。
ドキュメントには、発火日の変更は比較的費用がかかると記載されており、多くのsetFireDate:
ことを行わない限り、タイマーを破棄して再作成する方がよい場合があることを示唆しています。しかし、議論のために、私は少し前にこのカテゴリを作成しました。日付調整動作をカプセル化するので、これが好きです。所有者/コントローラーではなく、タイマー自体がそれを処理します。ただし、これに関するパフォーマンスデータはありません。
@implementation NSTimer (WSSAdjustingFireDate)
- (void)WSSFireAdjustingFireDate
{
[self fire];
[self WSSSkipNextFireAdjustingFireDate];
}
- (void)WSSSkipNextFireAdjustingFireDate
{
CFRunLoopTimerRef cfSelf = (__bridge CFRunLoopTimerRef)self;
CFTimeInterval delay = CFRunLoopTimerGetInterval(cfSelf);
CFRunLoopTimerSetNextFireDate(cfSelf, CFAbsoluteTimeGetCurrent() + delay);
}
@end
の作成を避けるために、CoreFoundation関数を使用しましたNSDate
。時期尚早の最適化?塩を渡してください。