SwiftUI'da NavigationStack: Modern Navigasyon Yönetiminin Rehberi
NavigationView'ın yerini alan Apple'ın güçlü yeni navigasyon sistemi NavigationStack'i öğrenin. Pratik örnekler ve en iyi uygulamalarla kapsamlı rehber.

SwiftUI’da NavigationStack: Modern Navigasyon Yönetiminin Rehberi
iOS 16 ile SwiftUI navigasyonunda en önemli gelişmelerden biri tanıtıldı: NavigationStack. Bu güçlü yeni API, eskiyen NavigationView’ın yerini alıyor ve geliştiricilere navigasyon akışları üzerinde eşi görülmemiş kontrol sağlıyor. NavigationStack hakkında bilmeniz gereken her şeyi derinlemesine inceleyelim.
Neden NavigationView Yerine NavigationStack?
🚫 NavigationView’ın Sorunları
NavigationView, geliştiricileri hayal kırıklığına uğratan birçok sınırlamaya sahipti:
// ❌ Eski NavigationView yaklaşımı - kullanımdan kaldırıldı
NavigationView {
List {
NavigationLink("Ayarlar", destination: AyarlarView())
NavigationLink("Profil", destination: ProfilView())
}
.navigationTitle("Ana Sayfa")
}
.navigationViewStyle(StackNavigationViewStyle()) // iPad'de gerekli
NavigationView’ın Sorunları:
- Cihazlar arası tutarsız davranış
- Sınırlı programatik navigasyon kontrolü
- Uygun navigasyon durum yönetimi yok
- Karmaşık deep linking uygulaması
- Büyük navigasyon yığınlarında performans sorunları
✅ NavigationStack Avantajları
// ✅ Yeni NavigationStack yaklaşımı
@State private var navigasyonYolu = NavigationPath()
NavigationStack(path: $navigasyonYolu) {
List {
Button("Ayarlara Git") {
navigasyonYolu.append("ayarlar")
}
Button("Profile Git") {
navigasyonYolu.append("profil")
}
}
.navigationDestination(for: String.self) { hedef in
switch hedef {
case "ayarlar":
AyarlarView()
case "profil":
ProfilView()
default:
EmptyView()
}
}
.navigationTitle("Ana Sayfa")
}
NavigationStack’in Faydaları:
- ✅ Programatik navigasyon kontrolü
- ✅ Tip güvenli navigasyon yolları
- ✅ Daha iyi performans ve bellek yönetimi
- ✅ Basitleştirilmiş deep linking
- ✅ Tüm cihazlarda tutarlı davranış
Temel NavigationStack Uygulaması
Basit Navigasyon Örneği
import SwiftUI
struct İçerikGörünümü: View {
var body: some View {
NavigationStack {
VStack(spacing: 20) {
NavigationLink("Detay Görünümüne Git") {
DetayGörünümü(başlık: "İlk Detay")
}
NavigationLink("Ayarlara Git") {
AyarlarView()
}
}
.navigationTitle("Ana Sayfa")
.navigationBarTitleDisplayMode(.large)
}
}
}
struct DetayGörünümü: View {
let başlık: String
var body: some View {
VStack {
Text("Bu \(başlık)")
.font(.largeTitle)
NavigationLink("Daha Derine Git") {
DetayGörünümü(başlık: "İç İçe Detay")
}
}
.navigationTitle(başlık)
.navigationBarTitleDisplayMode(.inline)
}
}
Yol Yönetimi ile Gelişmiş NavigationStack
Programatik Navigasyon Kontrolü
NavigationStack’in gerçek gücü, navigasyon durumunu programatik olarak yönetebilme kabiliyetinden gelir:
struct GelişmişNavigasyonÖrneği: View {
@State private var navigasyonYolu = NavigationPath()
var body: some View {
NavigationStack(path: $navigasyonYolu) {
VStack(spacing: 20) {
Button("Ayarlara Naviget Et") {
navigasyonYolu.append(Hedef.ayarlar)
}
Button("Profile Naviget Et") {
navigasyonYolu.append(Hedef.profil)
}
Button("İç İçe Görünüme Deep Link") {
// Birden fazla ekranda aynı anda navigasyon
navigasyonYolu.append(Hedef.ayarlar)
navigasyonYolu.append(AyarlarBölümü.gizlilik)
navigasyonYolu.append(GizlilikSeçeneği.veriPaylaşımı)
}
Button("Geri Git") {
if !navigasyonYolu.isEmpty {
navigasyonYolu.removeLast()
}
}
Button("Ana Sayfaya Git") {
navigasyonYolu = NavigationPath()
}
}
.navigationTitle("Gelişmiş Navigasyon")
.navigationDestination(for: Hedef.self) { hedef in
hedefGörünümü(for: hedef)
}
.navigationDestination(for: AyarlarBölümü.self) { bölüm in
AyarlarBölümGörünümü(bölüm: bölüm)
}
.navigationDestination(for: GizlilikSeçeneği.self) { seçenek in
GizlilikSeçenekGörünümü(seçenek: seçenek)
}
}
}
@ViewBuilder
private func hedefGörünümü(for hedef: Hedef) -> some View {
switch hedef {
case .ayarlar:
AyarlarAnaGörünümü(navigasyonYolu: $navigasyonYolu)
case .profil:
ProfilView()
}
}
}
enum Hedef: Hashable {
case ayarlar
case profil
}
enum AyarlarBölümü: String, Hashable, CaseIterable {
case gizlilik = "Gizlilik"
case güvenlik = "Güvenlik"
case bildirimler = "Bildirimler"
}
enum GizlilikSeçeneği: String, Hashable, CaseIterable {
case veriPaylaşımı = "Veri Paylaşımı"
case analitik = "Analitik"
case çerezler = "Çerezler"
}
Özel Türlerle Tip Güvenli Navigasyon
Sağlam Navigasyon Modelleri Oluşturma
class NavigasyonModeli: ObservableObject {
@Published var yol = NavigationPath()
func kullanıcıProfilineNavigetEt(_ kullanıcıID: String) {
yol.append(NavigasyonHedefi.kullanıcıProfili(kullanıcıID))
}
func gönderiyeNavigetEt(_ gönderiID: Int) {
yol.append(NavigasyonHedefi.gönderi(gönderiID))
}
func anaKökeGit() {
yol = NavigationPath()
}
func geriGit() {
if !yol.isEmpty {
yol.removeLast()
}
}
}
enum NavigasyonHedefi: Hashable {
case kullanıcıProfili(String)
case gönderi(Int)
case ayarlar
case profilDüzenle
// Daha iyi performans için özel hash uygulaması
func hash(into hasher: inout Hasher) {
switch self {
case .kullanıcıProfili(let id):
hasher.combine("kullanıcıProfili")
hasher.combine(id)
case .gönderi(let id):
hasher.combine("gönderi")
hasher.combine(id)
case .ayarlar:
hasher.combine("ayarlar")
case .profilDüzenle:
hasher.combine("profilDüzenle")
}
}
}
struct AnaNavigasyonGörünümü: View {
@StateObject private var navigasyonModeli = NavigasyonModeli()
var body: some View {
NavigationStack(path: $navigasyonModeli.yol) {
İçerikListeGörünümü(navigasyonModeli: navigasyonModeli)
.navigationDestination(for: NavigasyonHedefi.self) { hedef in
hedefGörünümü(for: hedef)
}
}
.environmentObject(navigasyonModeli)
}
@ViewBuilder
private func hedefGörünümü(for hedef: NavigasyonHedefi) -> some View {
switch hedef {
case .kullanıcıProfili(let kullanıcıID):
KullanıcıProfilGörünümü(kullanıcıID: kullanıcıID)
case .gönderi(let gönderiID):
GönderiDetayGörünümü(gönderiID: gönderiID)
case .ayarlar:
AyarlarView()
case .profilDüzenle:
ProfilDüzenleGörünümü()
}
}
}
Gerçek Dünya Örnekleri
Sosyal Medya Uygulaması Navigasyonu
struct SosyalMedyaNavigasyonu: View {
@State private var navigasyonYolu = NavigationPath()
@State private var seçiliTab = 0
var body: some View {
TabView(selection: $seçiliTab) {
NavigationStack(path: $navigasyonYolu) {
AkışGörünümü { gönderi in
navigasyonYolu.append(SosyalRota.gönderiDetayı(gönderi))
}
.navigationTitle("Akış")
.navigationDestination(for: SosyalRota.self) { rota in
sosyalHedef(for: rota)
}
}
.tabItem {
Image(systemName: "house.fill")
Text("Ana Sayfa")
}
.tag(0)
NavigationStack {
ProfilView { aksiyon in
profilAksiyonuİşle(aksiyon)
}
.navigationTitle("Profil")
}
.tabItem {
Image(systemName: "person.fill")
Text("Profil")
}
.tag(1)
}
}
@ViewBuilder
private func sosyalHedef(for rota: SosyalRota) -> some View {
switch rota {
case .gönderiDetayı(let gönderi):
GönderiDetayGörünümü(gönderi: gönderi) { kullanıcı in
navigasyonYolu.append(SosyalRota.kullanıcıProfili(kullanıcı))
}
case .kullanıcıProfili(let kullanıcı):
KullanıcıProfilGörünümü(kullanıcı: kullanıcı)
case .yorumlar(let gönderi):
YorumlarGörünümü(gönderi: gönderi)
}
}
private func profilAksiyonuİşle(_ aksiyon: ProfilAksiyonu) {
// Profil aksiyonlarını işle
}
}
enum SosyalRota: Hashable {
case gönderiDetayı(Gönderi)
case kullanıcıProfili(Kullanıcı)
case yorumlar(Gönderi)
}
NavigationStack ile Deep Linking
URL Tabanlı Navigasyon Uygulaması
struct DeepLinkNavigasyonGörünümü: View {
@State private var navigasyonYolu = NavigationPath()
var body: some View {
NavigationStack(path: $navigasyonYolu) {
AnaGörünüm()
.navigationDestination(for: DeepLinkHedefi.self) { hedef in
deepLinkHedefi(for: hedef)
}
.onOpenURL { url in
deepLinkİşle(url)
}
}
}
private func deepLinkİşle(_ url: URL) {
guard let bileşenler = URLComponents(url: url, resolvingAgainstBaseURL: false),
let host = bileşenler.host else { return }
// Mevcut navigasyonu temizle
navigasyonYolu = NavigationPath()
switch host {
case "kullanıcı":
if let kullanıcıID = bileşenler.queryItems?.first(where: { $0.name == "id" })?.value {
navigasyonYolu.append(DeepLinkHedefi.kullanıcı(kullanıcıID))
}
case "ürün":
if let ürünIDString = bileşenler.queryItems?.first(where: { $0.name == "id" })?.value,
let ürünID = Int(ürünIDString) {
navigasyonYolu.append(DeepLinkHedefi.ürün(ürünID))
}
case "ayarlar":
navigasyonYolu.append(DeepLinkHedefi.ayarlar)
default:
break
}
}
@ViewBuilder
private func deepLinkHedefi(for hedef: DeepLinkHedefi) -> some View {
switch hedef {
case .kullanıcı(let kullanıcıID):
KullanıcıDetayGörünümü(kullanıcıID: kullanıcıID)
case .ürün(let ürünID):
ÜrünDetayGörünümü(ürünID: ürünID)
case .ayarlar:
AyarlarView()
}
}
}
enum DeepLinkHedefi: Hashable {
case kullanıcı(String)
case ürün(Int)
case ayarlar
}
En İyi Uygulamalar ve Geçiş İpuçları
NavigationView’dan Geçiş
// Önce: NavigationView (Kullanımdan Kaldırıldı)
struct EskiNavigasyonGörünümü: View {
var body: some View {
NavigationView {
List {
NavigationLink("Ayarlar", destination: AyarlarView())
NavigationLink("Profil", destination: ProfilView())
}
.navigationTitle("Ana Sayfa")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
// Sonra: NavigationStack (Önerilen)
struct YeniNavigasyonGörünümü: View {
@State private var navigasyonYolu = NavigationPath()
var body: some View {
NavigationStack(path: $navigasyonYolu) {
List {
Button("Ayarlar") {
navigasyonYolu.append(Hedef.ayarlar)
}
Button("Profil") {
navigasyonYolu.append(Hedef.profil)
}
}
.navigationTitle("Ana Sayfa")
.navigationDestination(for: Hedef.self) { hedef in
switch hedef {
case .ayarlar:
AyarlarView()
case .profil:
ProfilView()
}
}
}
}
}
enum Hedef: Hashable {
case ayarlar
case profil
}
Performans Optimizasyon İpuçları
struct OptimizeNavigasyonGörünümü: View {
@State private var navigasyonYolu = NavigationPath()
var body: some View {
NavigationStack(path: $navigasyonYolu) {
İçerikGörünümü()
.navigationDestination(for: OptimizeRota.self) { rota in
optimizeHedef(for: rota)
}
}
}
@ViewBuilder
private func optimizeHedef(for rota: OptimizeRota) -> some View {
switch rota {
case .tembeleYüklenmiş(let id):
TembeleYüklenmiş DetayGörünümü(id: id)
.onAppear {
sonrakiGörünümüÖnYükle(for: id)
}
case .önbelleklenmişGörünüm(let veri):
ÖnbelleklenmişİçerikGörünümü(veri: veri)
}
}
private func sonrakiGörünümüÖnYükle(for id: String) {
// Ön yükleme mantığını uygula
}
}
enum OptimizeRota: Hashable {
case tembeleYüklenmiş(String)
case önbelleklenmişGörünüm(ÖnbelleklenmişVeri)
}
Sonuç
NavigationStack, SwiftUI navigasyon yeteneklerinde büyük bir sıçramayı temsil ediyor. Programatik kontrolü, tip güvenliği ve cihazlar arası tutarlı davranışı, modern iOS geliştirme için açık seçim yapıyor.
Önemli Çıkarımlar:
- Her zaman NavigationStack kullanın iOS 16+ hedefleyen yeni projeler için
- Uygun navigasyon durum yönetimi uygulayın karmaşık uygulamalar için
- Tip güvenli hedefler kullanın çalışma zamanı hatalarını önlemek için
- Deep linking stratejinizi planlayın geliştirmenin erken aşamasında
- Navigasyon akışlarını kapsamlı test edin farklı cihazlarda
Geçiş Zaman Çizelgesi:
- Hemen: Tüm yeni özellikler için NavigationStack kullanmaya başlayın
- Kısa vadeli: Kritik kullanıcı akışlarını NavigationView’dan geçirin
- Uzun vadeli: NavigationView kullanımdan kaldırıldıkça tam geçişi tamamlayın
NavigationStack sadece bir değişiklik değil—tamamen yeni kullanıcı etkileşim kalıplarını mümkün kılan güçlü bir araçtır. Ustalaşın ve doğal, duyarlı ve tamamen modern hissettiren navigasyona sahip uygulamalar oluşturun.
En son SwiftUI gelişmelerinden haberdar olmak mı istiyorsunuz? Haftalık ipuçları, eğitimler ve sektör içgörüleri için bültenimize abone olun.