Какие данные доступны в completion блоке анимации в iOS
Что проверяют
Знаете ли вы, что именно передаёт UIKit в completion и в каких случаях анимация считается незавершённой. Следом часто спрашивают про UIViewPropertyAnimator и про то, какое значение у свойства во время анимации.
Как отвечать
У UIView.animate(withDuration:animations:completion:) completion имеет тип ((Bool) -> Void)?, и единственный параметр это finished:
true: анимация доиграла до конца;false: её сняли раньше времени, например вызвалиlayer.removeAllAnimations(), вью ушло из иерархии или приложение ушло в фон.
Больше ничего блок не получает. Важная деталь: модельное значение свойства меняется сразу, в момент вызова блока animations. Если вы анимировали alpha в ноль, то view.alpha уже равен нулю и в completion, и во время анимации, даже при finished == false. Промежуточное значение на экране хранит слой отображения, его читают через view.layer.presentation().
Остальные API отличаются:
UIViewPropertyAnimator:addCompletion { position in }получаетUIViewAnimatingPosition(.start,.end,.current), то есть где анимация остановилась. ПослеstopAnimation(true)completion не вызывается вовсе, послеstopAnimation(false)его вызоветfinishAnimation(at:);CAAnimationDelegate:animationDidStop(_:finished:)отдаёт саму анимацию и тот же флаг;CATransaction.setCompletionBlock: без параметров;- SwiftUI:
withAnimationс completion появился в iOS 17, замыкание тоже без параметров.
Completion вызывается на главном потоке. Цикла удержания замыкание не создаёт, UIKit отпускает его после вызова, но объект проживёт до конца анимации.
Где спотыкаются
Думают, что при finished == false свойство вернулось к исходному значению. Нет, модель уже содержит конечное значение.
Кладут removeFromSuperview() только в ветку if finished. При прерывании вью останется в иерархии невидимым и продолжит перехватывать касания.
Путают stopAnimation(true) и stopAnimation(false) у аниматора и ждут completion, который не придёт.