В каком методе UIViewController можно вызывать анимации view
Что проверяют
Знаете ли вы жизненный цикл UIViewController настолько, чтобы объяснить, что именно пользователь увидит в каждом методе. Правильный ответ не «в viewDidAppear», а «зависит от анимации». Следом часто спрашивают, как анимировать изменение констрейнтов.
Как отвечать
Запустить анимацию можно в любом методе на главном потоке. Вопрос в том, будет ли view в этот момент на экране и с правильной геометрией:
viewDidLoad(): view ещё не в окне и размеры не финальные. Здесь задают начальное состояние, напримерalpha = 0, но не запускают анимацию;viewWillAppear(_:): экран ещё не виден. Подходит для анимации синхронно с переходом:transitionCoordinator?.animate(alongsideTransition:completion:);viewIsAppearing(_:): view уже в иерархии, trait collection и размеры актуальны. Метод появился в SDK iOS 17 и доступен начиная с iOS 13, Apple рекомендует его для настройки интерфейса перед показом;viewDidLayoutSubviews(): фреймы посчитаны, но метод вызывается много раз, запуск анимации здесь без флага даст повторы;viewDidAppear(_:): экран уже виден. Место для анимации появления, которую пользователь должен увидеть целиком.
Для Auto Layout схема такая: меняете constant у констрейнта, затем UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() }. Для прерываемых и интерактивных анимаций есть UIViewPropertyAnimator, для собственного перехода между экранами UIViewControllerAnimatedTransitioning.
Анимации в ответ на действие пользователя запускают прямо в обработчике, к жизненному циклу они не привязаны.
Где спотыкаются
Запускают анимацию в viewDidLoad. Пользователь её не видит: к моменту показа она уже закончилась.
Не задают начальное состояние до показа. В viewDidAppear элемент на мгновение виден в конечном виде, потом прыгает в начальный и анимируется, получается мерцание.
Забывают, что viewDidAppear вызывается при каждом появлении: после закрытия модального окна или возврата из push анимация проиграется снова, если не поставить флаг.