Edited at

[iOS]UIView.animateがキャンセルされ、completionが呼ばれる問題

長年疑問だった挙動を確認しました。

hogeViewX.constant = 100

UIView.animate(withDuration: TimeInterval(2.0),
animations: {
self.view.layoutIfNeeded() },
completion: { (finished) in
print("🤔")
})

例えばこういうアニメーションを、アニメーション中に複数回呼ぶと、前のがキャンセルされてcompletionが呼ばれます。

completionのfinishedはなぜかtrueを返すので、キャンセルされたかどうかがわかりません。


困ること

例えばanimationの発火ボタンを連打しても、問題ないように見えます。

しかし、completionで例えばisHidden = trueとしていたりすると厄介です。

アニメーション後に消えてほしいのに、2回目を押した瞬間に消えてしまいます。


回避方法1.フラグで管理

1回目のアニメーションが終わるまで他の同一のアニメーションを排除します

これは上手く動きました


回避方法2.別のアニメーションと判断させる

内部的に、animationの中身(アニメーション対象?)が同じなら同じアニメーションと判断しているようです。

なのでこういう風にanimationの中身を変えてしまえばゴリ押しで解決できるようです。

hogeViewX.constant = CGFloat(100 + Float.random(in: 0..<1.0))

UIView.animate(withDuration: TimeInterval(2.0),
animations: {
self.view.layoutIfNeeded() },
completion: { (finished) in
print("🤔")
})


回避方法3.他のアニメーションを使う

これはStackOverflowであったものの未確認


この問題に、どこで遭遇しやすいか

scrollViewDidScrollでアニメーションを呼ぶ時に起こりがちです


公式仕様は?

発見できませんでした

あまり話題になってるのも見たことがありません

でも私は定期的にこの問題に遭遇します