Programmatic Navigation & Deep Linking

Drive navigation from code, not just taps. Learn NavigationStack with a path binding, navigationDestination(for:) , pushing and popping in code, type-safe routes with an enum , and deep linking with onOpenURL .

Learn Programmatic Navigation & Deep Linking in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and…

Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Basic NavigationLink

A plain NavigationLink pushes a destination when the user taps it. That is fine for simple menus but gives you no control from code.

2️⃣ Programmatic Push and Pop

Bind a path to the NavigationStack . Append values to push, empty it to pop to root — all from your own code, not taps.

3️⃣ Type-Safe Routes with an Enum

A Hashable enum names every valid destination. A switch in navigationDestination(for:) forces you to handle each case.

Your turn. Fill in the path binding and the method that pushes a value.

4️⃣ Deep Linking with onOpenURL

onOpenURL fires when the app opens from a URL. Parse it into a route value and append it to the path to jump straight to the right screen.

📋 Quick Reference

Build a Hashable route enum, bind it to a NavigationStack, and push a profile screen from a button.

Practice quiz

Which container replaced NavigationView for stack navigation in modern SwiftUI?

  • NavigationStack
  • NavigationView
  • TabView
  • ScrollView

Answer: NavigationStack. NavigationStack is the modern push/pop container introduced in iOS 16.

What does binding a path to a NavigationStack let you do?

  • Add tabs
  • Style the bar
  • Drive navigation programmatically by editing the path array
  • Disable navigation

Answer: Drive navigation programmatically by editing the path array. A path binding holds the navigation stack so you can push and pop by mutating the array.

Which modifier registers what view to show for a given value type?

  • onAppear
  • navigationDestination(for:)
  • sheet(item:)
  • navigationTitle

Answer: navigationDestination(for:). navigationDestination(for:) maps a value type to the destination view it should present.

To pop to the root of a NavigationStack programmatically, you...

  • Call dismiss()
  • Remove the modifier
  • Restart the app
  • Set the path to an empty collection

Answer: Set the path to an empty collection. Emptying the path collection pops every pushed view back to the root.

How do you push a new screen programmatically with a path binding?

  • Append a value to the path
  • Toggle a Bool
  • Use a segue
  • Call push()

Answer: Append a value to the path. Appending a value to the bound path pushes its matching navigationDestination view.

Why use an enum for type-safe routes?

  • It avoids imports
  • It enumerates all valid destinations the compiler can check
  • It is required by SwiftUI
  • It is faster

Answer: It enumerates all valid destinations the compiler can check. An enum lists every valid route so the compiler catches typos and missing cases.

Which modifier handles an incoming deep-link URL?

  • onTapGesture
  • onChange
  • onReceive
  • onOpenURL

Answer: onOpenURL. onOpenURL(perform:) fires when the app is opened via a URL, letting you parse and route.

After parsing a deep-link URL, how do you navigate to that screen?

  • Show an alert
  • Ignore it
  • Append the parsed route value to the navigation path
  • Reload the app

Answer: Append the parsed route value to the navigation path. You translate the URL into a route value and append it to the path to navigate there.

How does NavigationLink(value:) differ from the basic NavigationLink(destination:)?

  • It opens a sheet
  • It pushes a value resolved by navigationDestination instead of an inline view
  • It does nothing
  • It is deprecated

Answer: It pushes a value resolved by navigationDestination instead of an inline view. NavigationLink(value:) sends a value that navigationDestination(for:) turns into a screen.

For routes to drive a path and be diffable, the route type should be...

  • Hashable
  • A class
  • Optional
  • Sendable only

Answer: Hashable. Path values must be Hashable so the stack can store and compare them.