November 3, 2026

Instinctivecode

Pengembangan aplikasi iOS & Mac, UX

Mengelola Navigasi SwiftUI: Panduan Langkah demi Langkah

Meja pengembang dengan laptop berisi kode dan ponsel menampilkan antarmuka aplikasi
Navigasi SwiftUI punya beberapa pilihan API. Panduan ini membandingkan NavigationStack, NavigationLink, dan NavigationSplitView lewat contoh kode.

Navigasi SwiftUI sering membingungkan karena ada beberapa API yang bisa dipakai untuk tujuan serupa. Panduan ini memandu Anda langkah demi langkah memilih dan menerapkan navigasi SwiftUI yang sesuai untuk aplikasi iOS maupun macOS, dengan perbandingan singkat di tiap langkah.

Langkah 1: Tentukan Pola Navigasi Aplikasi

Sebelum menulis kode, petakan dulu alur layar. Aplikasi dengan daftar ke detail cocok memakai tumpukan (stack). Aplikasi iPad atau Mac dengan sidebar dan panel detail membutuhkan tampilan terpisah (split view). Aplikasi yang berpindah antar tab memerlukan TabView sebagai wadah utama.

Tuliskan tiga hal: layar awal, layar yang bisa dicapai dari sana, dan apakah pengguna perlu kembali ke layar sebelumnya. Pola navigasi yang salah biasanya muncul karena langkah ini dilewati.

Langkah 2: Pilih Antara NavigationStack dan NavigationSplitView

NavigationStack menampilkan satu layar pada satu waktu dan menyimpan riwayat navigasi. Cocok untuk iPhone dan aplikasi yang alurnya linear. NavigationSplitView menampilkan dua atau tiga kolom berdampingan, cocok untuk iPad dan Mac.

Perbandingan singkatnya:

  • NavigationStack: satu jalur navigasi, kembali dengan tombol back, paling sederhana untuk dipelajari.
  • NavigationSplitView: sidebar, konten, dan detail bisa tampil bersamaan; di iPhone otomatis menyusut menjadi tumpukan.
  • TabView: bukan pengganti keduanya, melainkan wadah untuk beberapa alur navigasi independen.

Jika aplikasi Anda menargetkan iPhone saja, NavigationStack hampir selalu cukup. Untuk aplikasi macOS, NavigationSplitView lebih lazim karena memanfaatkan lebar jendela. Panduan membuat aplikasi macOS dengan SwiftUI membahas pola ini lebih jauh.

Langkah 3: Siapkan NavigationStack dengan Path

Langkah pertama dalam kode adalah membungkus tampilan utama dengan NavigationStack. Deklarasikan array sebagai path jika Anda ingin mengontrol navigasi secara programatis.

struct DaftarBuku: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            List(books) { book in
                NavigationLink(book.title, value: book)
            }
            .navigationDestination(for: Book.self) { book in
                DetailBuku(book: book)
            }
            .navigationTitle("Buku")
        }
    }
}

Dengan path sebagai @State, Anda bisa menambah atau menghapus halaman dari mana saja di dalam tampilan, misalnya setelah pengguna menyelesaikan formulir. Tanpa path, NavigationStack tetap bekerja, tetapi Anda kehilangan kendali programatis.

Langkah 4: Hubungkan NavigationLink ke Data

NavigationLink punya dua bentuk: tujuan langsung dan tujuan berbasis nilai. Bentuk berbasis nilai lebih fleksibel karena tujuan ditentukan di satu tempat melalui navigationDestination.

NavigationLink(value: book) {
    Text(book.title)
}

// Di dalam NavigationStack:
.navigationDestination(for: Book.self) { book in
    DetailBuku(book: book)
}

Keuntungan pendekatan ini: jika tipe data yang sama muncul di beberapa daftar, Anda cukup mendefinisikan tujuan sekali. Kekurangannya, tipe data harus Hashable dan Anda perlu memastikan setiap tipe yang mungkin muncul punya tujuan yang terdaftar.

Langkah 5: Atur Navigasi Antar Tab

Jika aplikasi memakai TabView, setiap tab sebaiknya memiliki NavigationStack sendiri. Ini mencegah riwayat satu tab bocor ke tab lain, yang sering terjadi ketika NavigationStack diletakkan di luar TabView.

TabView {
    NavigationStack {
        DaftarBuku()
    }
    .tabItem { Label("Buku", systemImage: "book") }

    NavigationStack {
        Pengaturan()
    }
    .tabItem { Label("Pengaturan", systemImage: "gear") }
}

Pisahkan path tiap tab jika Anda perlu mengatur ulang navigasi secara terpisah, misalnya saat pengguna logout. State management yang rapi membantu di sini; perbandingan Observable vs Environment bisa menjadi acuan.

Langkah 6: Uji Perilaku Kembali dan Deep Link

Setelah navigasi dasar berjalan, uji dua hal yang sering terlewat. Pertama, perilaku tombol kembali: apakah data di layar sebelumnya tetap utuh? Kedua, deep link: bisakah aplikasi membuka layar tertentu langsung dari tautan?

Deep link biasanya diterjemahkan menjadi penambahan nilai ke path. Jika path Anda bertipe NavigationPath, Anda bisa menambahkan beberapa nilai sekaligus untuk membentuk tumpukan. Untuk data pengguna yang sensitif, pertimbangkan juga perlindungan data seperti yang dibahas di cara melindungi data pribadi di aplikasi pinjaman online, karena prinsipnya berlaku umum untuk aplikasi apa pun.

Langkah 7: Tangani Kasus Tepi

Beberapa situasi perlu penanganan khusus. Jika pengguna membuka tautan ke halaman yang datanya belum dimuat, tampilkan status memuat sebelum mendorong halaman. Jika pengguna menekan tombol kembali saat proses berjalan, batalkan tugas yang sedang berjalan agar tidak memperbarui tampilan yang sudah hilang.

Untuk aplikasi yang mengandalkan data dari server, pastikan navigasi tidak macet saat koneksi terputus. Uji dengan simulasi jaringan lambat atau mati; metode pengujian konektivitas seperti yang diuraikan di 7 metode uji konektivitas jaringan bisa membantu merencanakan skenario ini.

Ringkasan

Navigasi SwiftUI yang baik dimulai dari pemetaan alur, bukan dari kode. Pilih NavigationStack untuk alur linear, NavigationSplitView untuk iPad dan Mac, dan beri setiap tab NavigationStack sendiri. Gunakan NavigationLink berbasis nilai agar tujuan terdefinisi di satu tempat, lalu uji kembali dan deep link sebelum rilis.

Pertanyaan yang Sering Diajukan

Apakah NavigationStack bisa dipakai di macOS?

Bisa, tetapi untuk aplikasi Mac dengan sidebar, NavigationSplitView lebih sesuai karena memanfaatkan lebar jendela. NavigationStack di Mac terasa sempit jika hanya menampilkan satu kolom.

Kapan sebaiknya memakai NavigationPath dibanding array biasa?

NavigationPath cocok jika tipe halaman beragam dan Anda tidak ingin mendeklarasikan satu tipe tertentu. Jika semua halaman berasal dari satu tipe data, array biasa lebih sederhana dan lebih mudah diperiksa.

Bagaimana cara kembali ke layar awal dari dalam kode?

Kosongkan path dengan path = NavigationPath() atau hapus nilai terakhir dengan path.removeLast(). Pastikan path dideklarasikan sebagai @State atau berada di observable object yang bisa diakses dari tampilan yang memicunya.