В
iOS 27 SwiftUI получил обновление для управления анимациями при навигации. Раньше для переходов было только два встроенных варианта:
.automatic и
.zoom(sourceID:in:). Теперь добавили
.crossFade и
AnyNavigationTransition. Это дает больше гибкости без необходимости писать кастомные решения.
Проблема с zoom:
ZoomNavigationTransition хорошо работает, когда у перехода есть визуальный источник. Пользователь тапает карточку или ячейку, и она плавно расширяется до полноэкранного вида. Это выглядит естественно.
Но что делать, если экран открывается по-другому? Например, из
deeplink, уведомления,
App Intent или
Siri. В таких случаях у системы нет визуальной точки отсчета.
Zoom становится искусственным и неестественным.
Решение - crossFade:
В
iOS 27 появился
CrossFadeNavigationTransition. Это новый тип перехода, который не требует источника. Экран просто плавно появляется через затемнение, без привязки к какому-либо элементу.
.sheet(isPresented: $showInfo) {
LandmarkInfo()
.presentationDetents([.medium])
.navigationTransition(.crossFade)
}
Идеально для случаев, где у системы нет визуального источника. Например, открытие по уведомлению или из виджета.
Динамический выбор перехода через AnyNavigationTransition:
Второе нововведение -
AnyNavigationTransition. Раньше
.navigationTransition(_:) требовал конкретный тип на месте вызова. Нельзя было выбрать переход динамически, в зависимости от того, как был открыт экран.
Теперь можно обернуть любой переход в
AnyNavigationTransition и использовать как значение.
struct LandmarkInfo: View {
var useCrossFade: Bool
var transition: AnyNavigationTransition {
useCrossFade
? AnyNavigationTransition(.crossFade)
: AnyNavigationTransition(.automatic)
}
var body: some View {
InfoContent()
.presentationDetents([.medium])
.navigationTransition(transition)
}
}
Один и тот же экран может открываться по-разному. По тапу - используем
zoom. Из уведомления -
crossFade. По диплинку -
automatic. И это работает без дублирования кода.
Важное замечание:
Кастомные переходы все еще не поддерживаются. Но
iOS 27 уже убирает часть странных компромиссов, которые были в
SwiftUI анимациях до этого.
Вывод:
CrossFadeNavigationTransition решает проблему переходов без визуального источника.
AnyNavigationTransition позволяет выбирать переход динамически в зависимости от контекста.
Современные приложения открываются не только по тапу на ячейку. Виджеты, уведомления,
Siri,
universal links - каждый сценарий требует своего поведения. Новые
API делают навигацию в
SwiftUI более гибкой и естественной.