NavigationStack је савремени навигациони контејнер у SwiftUI, представљен у iOS 16+ који је заменио NavigationView. Према Apple Developer Documentation, 2024, NavigationStack управља стеком екрана путем типно безбедног пута навигације (NavigationPath), подржава дубоку навигацију, програмски повратак на почетни екран и чување стања при промени података. За разлику од NavigationView, NavigationStack не захтева умотавање у додатни контејнер и пружа директан Binding ка путу навигације.
Главно
NavigationStack је контејнерско View које имплементира навигацију засновану на стеку (LIFO). Управља историјом прелазака, омогућавајући постављање нових екрана на стек и повраћање путем системског дугмета «Назад» или програмски. NavigationStack је део SwiftUI-а од iOS 16, iPadOS 16, macOS 13, watchOS 9 и tvOS 16.
Главна иновација NavigationStack-а је типно безбедан пут навигације. Уместо директног наводења destination при креирању NavigationLink-а, постављате вредност (value) у пут, а регистрација циљног View-а се одвија посебно кроз модификатор .navigationDestination(for:destination:). Ово раздваја навигацију и приказ, чинећи код модулнијим и тестабилнијим.
Према WWDC 2022 (Session 10054), NavigationStack користи нови механизам навигације заснован на ObservableObject и животном циклусу SwiftUI-а. За разлику од NavigationView који се ослањао на UINavigationController испод хаубе, NavigationStack је у потпуности имплементиран у SwiftUI-у, што побољшава предвидљивост и компатибилност са животним циклусом SwiftUI-а.
NavigationStack прихвата корени View и опционални пут навигације (Binding ка NavigationPath или низу Hashable вредности). Сви подређени екрани се постављају у стек путем NavigationLink-а или програмског додавања вредности у пут.
NavigationView је био главни навигациони контејнер SwiftUI-а до iOS 16. Аутоматски је управљао UINavigationController-ом испод хаубе, што је доводило до низа проблема: непредвидиво понашање при промени података, тешкоће са програмском навигацијом и недостатак типне безбедности.
| Карактеристика | NavigationStack (iOS 16+) | NavigationView (iOS 13–15) |
|---|---|---|
| Тип навигације | Стек (LIFO) | Стек (LIFO) |
| Пут навигације | Типизован (NavigationPath) | Није подржан |
| Deep linking | Уграђена подршка | Захтева хакове |
| Програмски повратак | Кроз пут (pop, popToRoot) | dismiss, presentationMode |
| Испод хаубе | SwiftUI native | UINavigationController |
| Компатибилност | iOS 16+ | iOS 13+ |
Кључна предност NavigationStack-а — типно безбедна навигација. Дефинишете пут као низ конкретних типова (или NavigationPath за хетерогене стекове) и региструјете destination за сваки тип. Ово елиминише грешке непоклапања типова и чини навигацију предвидљивом.
NavigationView је застарео у iOS 17. Apple препоручује миграцију на NavigationStack за све нове пројекте и при ажурирању минималне верзије на iOS 16.
NavigationPath је тип који представља пут навигације у NavigationStack-у. Може да чува хетерогене вредности (AnyHashable) или да се користи са одређеним типом путем Binding-а ка низу [T: Hashable]. NavigationPath се аутоматски кодира и декодира ради чувања стања.
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
HomeView()
.navigationDestination(for: String.self) { value in
DetailView(id: value)
}
.navigationDestination(for: Int.self) { value in
NumberView(number: value)
}
}
}
func goToRoot() {
path.removeLast(path.count)
}
func pushDeepLink() {
path.append("detail_42")
}
}
Хетерогени стек: NavigationPath може да садржи вредности различитих типова, ако имплементирају Hashable. На примјер, први екран може да прихвата String (ID), други — Int (број), трећи — прилагођени enum Route. За приказ сваког типа региструје се посебан .navigationDestination.
Codable подршка: NavigationPath имплементира Codable ако су све вредности у путу такође Codable + Hashable. Ово омогућава чување и опорављање стања навигације при поновном покретању апликације или преласку у позадину.
.navigationDestination(for:destination:) — модификатор који региструје циљно View за одређени тип података. Када NavigationLink постави вредност овог типа у пут, SwiftUI аутоматски проналази одговарајући .navigationDestination и креира екран.
enum AppRoute: Hashable {
case profile(UserID)
case settings
case about
}
struct AppNavigation: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
HomeView()
.navigationDestination(for: AppRoute.self) { route in
switch route {
case .profile(let id):
ProfileView(userId: id)
case .settings:
SettingsView()
case .about:
AboutView()
}
}
}
}
}
// Navigate: path.append(AppRoute.profile("user_123"))
Важно правило: .navigationDestination мора бити примењен на View које се налази унутар NavigationStack-а, и пре него што NavigationLink постави вредност у пут. Обично се додаје на корени View или на контејнер секције. Ако .navigationDestination није пронађен за тип вредности, прелаз неће се догодити.
Према SwiftUI Engineering (2023), .navigationDestination може бити регистрован на различитим нивоима хијерархије. SwiftUI тражи најближи одговарајући destination при покушају навигације. Ово омогућава прегаћање destination за један тип у различитим деловима апликације.
Образац 1: навигација кроз enum Route. Дефинишите enum са повезаним вредностима за све екране апликације. Користите један .navigationDestination за AppRoute и switch за усмеравање. Ово осигурава јединствени извор истине за све могуће преласке у апликацији.
struct StoreView: View {
@State private var path: [ProductRoute] = []
var body: some View {
NavigationStack(path: $path) {
ProductGrid()
.navigationDestination(for: ProductRoute.self) { route in
switch route {
case .detail(let product):
ProductDetail(product: product)
case .reviews(let productId):
ReviewsView(productId: productId)
}
}
}
}
}
enum ProductRoute: Hashable {
case detail(Product)
case reviews(String)
}
Образац 2: програмска навигација и deep linking. NavigationStack омогућава програмско управљање стеком: додавање, уклањање екрана и повратак на корен. Ово је потребно за push обавештења, дубоких линкова и опорављања навигације након поновног покретања.
Образац 3: низ типова уместо NavigationPath-а. Ако сви екрани користе један тип (нпр. String или прилагођени enum), користите Binding ка [T]. Ово пружа строжију типизацију и бољу перформансу од NavigationPath-а. NavigationPath је оправдан за хетерогене стекове са различитим типовима екрана.
Према Point-Free (2024), NavigationStack са enum Route је пожењни начин организације навигације у SwiftUI апликацијама. Чини све могуће преласке експлицитним, типно безбедним и тестабилним, што је посебно важно за велике пројекте са десетинама екрана.
Често постављана питања
NavigationStack — навигациони контејнер SwiftUI (iOS 16+), који управља стеком екрана путем типно безбедног пута. Заменио је NavigationView, нудећи подршку за deep linking, програмску навигацију и чување стања.
NavigationStack користи типно безбедан пут (NavigationPath) уместо директног повезивања NavigationLink-а са destination. Подржава програмску навигацију, deep linking и Codable за чување стања. Ради на SwiftUI-у, а не кроз UINavigationController.
NavigationPath је тип који представља секвенцу екрана у стеку. Додајете вредности у пут кроз path.append() или кроз NavigationLink са value. За приказ сваког типа региструје се .navigationDestination. NavigationPath подржава Codable и аутоматско чување стања.
Кроз програмско управљање путем: након обраде URL-а, позовите path.append() са одговарајућом вредношћу руте. NavigationStack аутоматски ће приказати циљни екран. Повратак на корен — path.removeLast(path.count).
Да, ако је ваша минимална верзија iOS 16+. NavigationView је застарео у iOS 17. Миграција пружа типно безбедну навигацију, подршку deep linking-а и бољу усклађеност са животним циклусом SwiftUI-а. За пројекте са iOS 15 и ниже још увијек користите NavigationView.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође