【Swift5】UIViewPropertyAnimatorでrepeatをする方法

はじめに

こんにちは。個人のアプリ開発をしていて、UIViewPropertyAnimatorを使ってアニメーションのリピートをさせたくなりました。
しかし、iOS13.0でrepeat指定など、使えなくなった書き方が多々あり、実装に詰まったので書き残したいと思います。参考になれば幸いです。

iOS13でのリピート動作の問題について

setAnimationRepeatCountのdeprecated

iOS13前では、アニメーションのリピートの回数をanimationsブロックで記述することで指定できる設定メソッド、setAnimationRepeatCount:がありました。
しかし現在は利用が非推奨のようなので、この方法は使えませんでした。

UIView.AnimationOptionsの.repeatが機能しない

iOS13以降の現象?なのか、runningPropertyAnimator(withDuration:delay:options:animations:completion:)メソッドで指定できるoptions[.curveLinear, .repeat]等を設定しても、無視されるようで動作しませんでした。

解決方法

この他にTimerクラスを利用する方法がありましたが、アニメーション時間の管理が大変そうだったので、今回はアニメーションのaddCompletion(_:)内であらかじめ関数で用意しておいた自分自身を呼ぶ再帰的な処理(少し不安ですが…)でリピート処理を行いました。

UIViewPropertyAnimatorの注意点など

Animatorの再利用について

私は、UIViewPropertyAnimatorは先にアニメーションと完了処理を登録するので、アニメーション前の状態にプロパティを戻して、
再度self.animator.startAnimation()を呼び出せば同じアニメーションが呼ばれると勘違いしました。(恥ずかしい)
実際は、Timerの再利用ができないように、Animatorも再利用ができないようです。同じアニメーションを実行するにはコンストラクタで再度インスタンスを生成する必要があります。

アニメーションの遅延実行について

UIViewPropertyAnimatorUIView.animateにて、アニメーションをaddCompletion(_:)でつなげて実行していくような際に、以下のようなanimationsブロックで、何も処理しないアニメーションを作成すれば、指定秒数待機するようにできると勘違いしました。実際は、アニメーションはdurationdelayの値は適用されず、すぐにアニメーションの完了が呼ばれます

そもそも、UIViewのアニメーションでは、animationsブロックにアニメーション対象となるプロパティの変更を行わないといけないようでした。(恥ずかしい)

なので少し違和感がありますが、以下のようにasyncAfterを利用するしかないようでした。

さいごに

見ていただいてありがとうございます。何か他に知見があればぜひコメントを頂けたら嬉しいです。

参考

参考 How can I repeat animation (using UIViewPropertyAnimator) certain number of times?stackoverflow 参考 Repeat/Autoreverse animations in iOS 13.xstackoverflow 参考 UIViewPropertyAnimatorapple Developer Documentation

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です