これは、 NSTimer のリアルタイム動作に関する質問に答える可能性があります。
タイマーはリアルタイムのメカニズムではありません。タイマーが追加された実行ループ モードの 1 つが実行中で、タイマーの起動時間が経過したかどうかを確認できる場合にのみ起動します。典型的な実行ループが管理するさまざまな入力ソースのため、タイマーの時間間隔の有効な分解能は 50 ~ 100 ミリ秒程度に制限されます。長いコールアウト中、または実行ループがタイマーを監視していないモードのときにタイマーの起動時間が発生した場合、実行ループが次にタイマーをチェックするまで、タイマーは起動しません。したがって、タイマーが潜在的に起動する実際の時間は、スケジュールされた起動時間よりもかなりの時間になる可能性があります。
NSRunLoopCommonModes
NSTimer のスケジュール方法は指定しませんが、次の代わりにスケジュールすると、パフォーマンスが向上する場合がありますNSRunLoopDefaultModes
。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
これで改善されない場合は、低レベルの代替手段を探す必要があります。
特に、次のことを調べることができますCADisplayLink
。
CADisplayLink オブジェクトは、アプリケーションが描画をディスプレイのリフレッシュ レートに同期できるようにするタイマー オブジェクトです。
これは、NSTimer と非常によく似た方法で使用できます。
CADisplayLink の利点は、リフレッシュ レートにリンクされていることです。そのため、1/60 秒の時間間隔でかなり信頼性の高い動作が得られるはずです。
CADisplayLink の使用例:
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(respondToTimer)];
[displayLink setFrameInterval:60];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
respondTimer
これにより、60 のリフレッシュ フレームごとに、つまり 1 秒に 1 回呼び出されます。メソッドを 1 つだけ呼び出す必要があるため、次を使用できます。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self respondToTimer];
});
そして、それはおそらくあなたにとってより簡単になるでしょう. (もちろん、[self RespondToTimer] への呼び出しをそのメソッドの完全な実装に置き換えることができます)。