Implement SwiftUI Navigation With NavigationStack and NavigationSplitView | by Rob Sturgeon | Jul, 2022

Apple has deprecated NavigationView, but the future is already here

Image by Firmbee from Pixabay

Apple has deprecated NavigationView, which was previously used as a wrapper for what was essentially a stack of views that are pushed when presented and popped when dismissed. It’s the familiar way that iOS navigation has worked since the beginning, without a physical back button but with a navigation bar at the top with a back button that describes where ‘back’ is.

There are two new ways of implementing navigation, but they end up looking pretty similar on an iPhone for reasons I’ll discuss later.

Let’s get started!

This app starts pretty simply with a couple of Hashable and Identifiable structures.

It’s necessary that the Screen enum storing the navigation state is Hashable, as it’s required by the new initialiser for NavigationLink that I’ll use later. In order to be Hashable the associated values need to be Hashable as well. This would still be true if they were just a String and an Int, but I want to make use of ForEach which requires that the types are also Identifiable. As raw value types String and Int are interchangeable, and they do not have unique attributes that define them.

I’ve added the data to ContentView as two arrays.

I could (and probably should) use an ObservableObject to store the data, but I’d rather write more code to demonstrate navigation specifically.

Now I have data but nowhere to display it.

Here’s a simple List with a Section for words and another for numbers.

Each word and number becomes a NavigationLink that will pass a Screen value as the navigationDestination, which does not yet exist.

Now I can finally finish the app by putting an ItemsListView in a NavigationStack and adding the navigationDestination. This takes any case of the Screen enum, so I’m using a switch to determine what to do based on the given value.

In this case all I’m doing here is displaying the values, but obviously these could be completely different screens that display their data in completely different ways.

The iPad is an obvious choice for using a NavigationSplitView.

The detail column is always shown, even if you only have don’t have a NavigationLink.

This means that anything you do to change the State, such as changing a State property, will update the detail column if it uses that property.

Screenshot by author

It took me a while to work out how to make a NavigationSplitView work on an iPhone. A regular Button that modifies a State property to set a selected item will not cause anything to happen.

This is because on an iPhone there is effectively a NavigationStack, while on iPad there is plenty of space for a sidebar.

In other words, the detail column cannot be shown without some sort of navigation.

Screenshot by author

To solve this, I am using a NavigationLink that sets a value.

This gives me the behavior I want on both iPhone and iPad, without the need to write platform-specific code.

Thanks for reading!

Want Daily Coding Tips like these?These tips previously appeared in my newsletter Type Safely.

News Credit

%d bloggers like this: