2

iOS用のアニメーションで線を書いていました。線はCGPathの点のセットとしてCALayerに描画されます。線は、フラットな位置から、異なるy座標を持つ「成形」形状にアニメーション化されますが、常に同じx座標は、折れ線グラフのアニメーションのようなものです。

ポイントの補間を簡単にするために、カスタムCGFloatプロパティをCALayerサブクラスに追加しました。私はこのプロパティを「アニメーター」と呼んでいます(より良い名前はprogress、interpolatorなどです)。このプロパティに0.0fから1.0fまでの単純なCABasicAnimationを追加して、CoreAnimationのタイミング関数と補間サポートを使用できるようにするというアイデアでした。それでも、カスタムアニメーションを簡単に作成できます。たとえば、ラインのポイントがy=100からy=130に移動する場合、アニメーターが0.0fのとき、私は100になり、1.0fのとき、ポイント130になります。中間値は、中間ポイントとIを示します。これらの新しいポイントで線を描き直して、アニメーションを取得します。

これでアニメーションは正常に機能し、レイヤーアクションを無効にしたり、needsDisplayForKeyを追加したりしましたが、私の問題はCoreAnimationが正確ではないことです。アニメーターの最終的な値は、1.0ではなく.95.96などになる場合があります。浮動小数点数には精度の問題があるため、これは問題ありませんが、モデル値が更新されると(アニメーションをレイヤーに追加する前に1.0fに設定)、線が再描画され、正確なビジュアルが得られるはずです。

ここで別の問題が発生します。アニメーションがすぐに削除されない場合があります。ほとんどの場合、すぐに削除され、問題はありませんが、数秒間、場合によっては数分間オンのままになることもあります。アニメーションが削除されないという私の理論をテストするために、単純なBOOLフラグをレイヤーに追加しました。これは、プレゼンテーションレイヤーにいるときにYESを返します。確かに、最後のdrawInContext呼び出しが、アニメーター値が0.98967fか何か、そしてアニメーター1.0fとプレゼンテーション層フラグがNOである最後のdrawInContext呼び出しは、ずっと後に起こります。その結果、私の視覚的なジャンプは、明らかな恐ろしいユーザーエクスペリエンスを除けば、正確ではありません。

私は自分の問題をできる限り説明しようとしました。誰かがコードを見たいと思ったら、私のテストプロジェクトを喜んで提供します。賢い人がこれを見て、私を助けてくれることを願っています。

編集1:Xcodeプロジェクト全体(私が試したことをすべて表示するための厄介な編集を含む)をここにアップロードしました。

編集2:完了時にアニメーションを手動で削除する同様の問題を抱えている人http://lucas.tiz.ma/blog/2012/04/18/core-animation-is-a-bit-garbage-collection-y/

ありがとう。

4

1 に答える 1

0

tl; dr AnimationDidStop:finishedでsetNeedsDisplayを明示的に呼び出します:コールバックを委任します。

Lucas Tizmaの投稿(上記の編集2を参照)に従って、アニメーションを手動で削除してみました。私は、アニメーションのデリゲートとしてレイヤーを設定することにより、彼のブロックベースのアプローチよりも単純なアプローチを選択しました。このようにして、アニメーションの開始と停止のコールバックが関連するレイヤーに直接送られます。AnimationDidStop:finishedでアニメーションを明示的に削除します。コールバックしても問題は修正されません。たとえば、アニメーションが停止し、削除されたことを確認すると、削除されたことが示されることがありますが(以下のログ、特にタイムスタンプを参照)、実際のモデル値を使用した正確な描画はかなり遅れて行われます。

// animationDidStop:finished: call back code

NSLog(@"layer animation stopped");

// check if any animations exist
NSLog(@"animation keys: %@", [self animationKeys]);

// remove animations and check
NSLog(@"removing animations");
[self removeAllAnimations];
NSLog(@"animation keys: %@", [self animationKeys]);

// log

2012-10-11 11:47:16.774 ASPathAnimationTest[3017:c07] on presentation layer 1
2012-10-11 11:47:16.774 ASPathAnimationTest[3017:c07] 335 animation draw update, animator is 0.982606
2012-10-11 11:47:16.775 ASPathAnimationTest[3017:c07] startPoint: {100, 90} - endPoint: {100, 100} - newPoint: {100, 99.8261}
<snip>
2012-10-11 11:47:16.791 ASPathAnimationTest[3017:c07] startPoint: {1000, 50} - endPoint: {1000, 100} - newPoint: {1000, 99.1303}
2012-10-11 11:47:16.792 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.792 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.793 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.793 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.794 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.794 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.794 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.795 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.795 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.819 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.820 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.820 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.821 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.821 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.821 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.822 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.822 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.822 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.823 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.823 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:48:00.000 ASPathAnimationTest[3017:c07] on presentation layer 0
2012-10-11 11:48:00.000 ASPathAnimationTest[3017:c07] 336 animation draw update, animator is 1.000000
<snip, there are 5 lines so draw and point logs go here>
2012-10-11 11:48:00.021 ASPathAnimationTest[3017:c07] 340 animation draw update, animator is 1.000000
2012-10-11 11:48:00.023 ASPathAnimationTest[3017:c07] startPoint: {100, 90} - endPoint: {100, 100} - newPoint: {100, 100}
<snip>
2012-10-11 11:48:00.026 ASPathAnimationTest[3017:c07] startPoint: {1000, 50} - endPoint: {1000, 100} - newPoint: {1000, 100}

ログを見て、アニメーションが実際に削除されていることに気付いた後、実際の正確なモデル値での再描画は、数秒または数分後までアニメーションが変更されない場合があります。animationDidStop:finished:デリゲートコールバックを明示的に呼び出すレイヤー上のsetNeedsDisplay。ビンゴ。

于 2012-10-11T07:45:24.220 に答える