なぜこれが起こっているのかについてのアイデアはありますか?
簡単な答えは、あなたの場合、非同期プッシュ モデルに基づいてアクション (アニメーション) を実行しており、使用しているメカニズムが実行中のタスクに適していないということです。
その他の注意事項:
NSTimer
解像度が低い。
- 作業はメインの実行ループで実行されます。そのスレッドでの作業の進行中に多くの時間が費やされ、タイマーの起動がブロックされる可能性があるため、予期したときにタイマーが起動しない場合があります。プロセス内の他のシステム アクティビティやスレッドによって、この変動がさらに大きくなる可能性があります。
- 同期されていない更新は、コールバックで実行する更新が発生後のある時点でポストされるため、多くの不要な作業や途切れが発生する可能性があります。これにより、更新のタイミングの精度がさらに変化します。更新が同期されていない場合、フレームをドロップしたり、大量の不要な作業を実行したりするのは簡単です。このコストは、図面が最適化されるまで明らかにならない場合があります。
ドキュメントからNSTimer
(強調鉱山):
タイマーはリアルタイムのメカニズムではありません。タイマーが追加された実行ループ モードの 1 つが実行中で、タイマーの起動時間が経過したかどうかを確認できる場合にのみ起動します。典型的な実行ループが管理するさまざまな入力ソースのため、タイマーの時間間隔の有効な分解能は 50 ~ 100 ミリ秒程度に制限されます。長いコールアウト中、または実行ループがタイマーを監視していないモードにある間にタイマーの起動時間が発生した場合、実行ループが次にタイマーをチェックするまで、タイマーは起動しません。したがって、タイマーが起動する実際の時間は、スケジュールされた起動時間よりもかなり長い時間になる可能性があります。
図面を最適化する準備ができている場合、問題を解決する最善の方法はCADisplayLink
、他の人が述べたように、を使用することです。これCADisplayLink
は iOS の特別な「タイマー」で、画面のリフレッシュ レートの (可能な) 分割でコールバック メッセージを実行します。これにより、アニメーションの更新を画面の更新と同期させることができます。このコールバックはメイン スレッドで実行されます。注: この機能は、複数のディスプレイが存在する可能性がある OS X ではあまり便利ではありません ( CVDisplayLink
)。
したがって、表示リンクを作成することから始めて、そのコールバックで、アニメーションと描画関連のタスクを処理する作業を実行できます (必要な-setNeedsDisplayInRect:
更新を実行するなど)。作業が非常に高速で、レンダリングも高速であることを確認してください。そうすれば、高いフレーム レートを達成できるはずです。このコールバックでの低速な操作は避けてください (ファイル io やネットワーク リクエストなど)。
最後に 1 つ: 私は、実行ループ (さまざまな頻度で実行するなど) に多くのタイマーをインストールするのではなく、タイマー同期コールバックを 1 つのメタコールバックにクラスター化する傾向があります。現時点でどの更新を実行するかを実装ですばやく判断できる場合、インストールするタイマーの数を大幅に (正確に 1 つに) 減らすことができます。