Driving NavigationSplitView with something other than List?

Is it possible to drive NavigationSplitView navigation with a view in sidebar (left column) that is not a List? All examples that I have seen from this year only contain List in sidebar.

I ask this because I would like to have a more complex layout in sidebar (or first view on iOS) that contains a mix of elements, some of them non-interactive and not targeting navigation. Here’s what I would like to do:

import SwiftUI

struct Thing: Identifiable, Hashable {
    let id: UUID
    let name: String
}

struct ContentView: View {
    let things: [Thing]
    @State private var selectedThingId: UUID?
    
    var body: some View {
        NavigationSplitView {
            ScrollView(.vertical) {
                VStack {
                    ForEach(things) { thing in
                        Button("Thing: \(thing.name) \( selectedThingId == thing.id ? "selected" : "" )") {
                            selectedThingId = thing.id
                        }
                    }
                   SomeOtherViewHere()
                   Button("Navigate to something else") { selectedThingId = someSpecificId }
                }
            }
        } detail: {
            // ZStack is workaround for known SDK bug
            ZStack {
                if let selectedThingId {
                    Text("There is a thing ID: \(selectedThingId)")
                } else {
                    Text("There is no thing.")
                }
            }
        }
    }
}

This actually works as expected on iPadOS and macOS, but not iOS (iPhone). Tapping changes the selection as I see in the button label, but does not push anything to navigation stack, I remain stuck at home screen.

Also filed as FB10332749.

Post not yet marked as solved Up vote post of Jaanus Down vote post of Jaanus
310 views

Replies

@Jaanus,

Have you tried composing your NavigationSplitView with a NavigationStack as your detail? You can then control push / pop behavior with a bound NavigationPath type. You mentioned your button doesn't push anything on the navigation stack, but I don't see a NavigationStack in your view's body.

All of my views are List driven but worth a shot. If you haven't already seen this video, check it out: https://developer.apple.com/wwdc22/10054

I don’t need NavigationStack as my detail. What I meant is that NavigationSplitView behaves as stack on iPhone, yet it doesn’t seem to have the kind of programmatic control for navigation that NavigationStack has. If I had NavigationStack as my content/detail view, it wouldn’t help with controlling navigation on the first level (sidebar).

I have seen the video. Everything about NavigationStack there looks great, but it doesn’t help me. All NavigationSplitView examples there are with a simple list in sidebar. It appears there is some magic going on with binding the List selection to NavigationSplitView state. I can’t figure out how it should behave with non-List or if it’s even possible.

I'm having the same issue using a LazyVStack in my sidebar. As of beta 1, it appears that NavigationSplitView doesn't work on iPhone.

Update: Unless I'm missing something, it appears that beta 2 does not work either.