0

I am building an app using NavigationSplitView, when previewing on Mac I can simply use List(selection: $selected) to highlight an item by default. Whether the correct content or details panel is populated is not an issue, because I can always set the default manually.

When moving to iPadOS, Xcode continually throws errors because it is considered an iOS device where this option is not available.

Here's a rough example of my view:

struct SidebarView: View {
    @State var selected: Int = 0
    
    var body: some View {
        #if os(macOS)
        List(selection: $page) {
            NavigationLink {
                MyPrimaryView()
            } label: {
                Label("Primary View", systemImage: "pencil.and.outline")
            }
            .tag(0)
            NavigationLink {
                Text("More!")
            } label: {
                Label("Secondary View", systemImage: "plus")
            }
            .tag(1)
        }
        #else
        List {
            NavigationLink {
                MyPrimaryView()
            } label: {
                Label("Primary View", systemImage: "pencil.and.outline")
            }
            NavigationLink {
                Text("More!")
            } label: {
                Label("Secondary View", systemImage: "plus")
            }
        }
        .navigationTitle("Mecurion")
        #endif
    }
}

On macOS, the first block of code is used and thanks to selection: $page, the first item in the list is highlighted. I have tried adding os(iPadOS) to the check and while this does not cause an error it does not appear to have any validity as a check itself.

On iPadOS, iOS and visionOS, the top item is never highlighted because this functionality is not available. Ideally, I would have the first item selected but a suitable workaround would be to highlight it instead. I am using NavigationLinks in the sidebar and content panels to drive the content changes and the app functions as expected apart from this confusion on devices larger than an iPhone.

This does not appear to be an uncommon pattern to want to follow. The Settings, Health, Passwords and News app all work this way so I am wondering if I am just taking completely wrong approach or if there is a common way to handle this or perhaps there is a different user experience I should be considering?

1 Answer 1

1

One possibility might be to use init(_:id:selection:rowContent:). For example:

@State var selected: Int? = 0
List([0, 1], id: \.self, selection: $selected) { page in
    if page == 0 {
        NavigationLink {
            Text("MyPrimaryView")
        } label: {
            Label("Primary View", systemImage: "pencil.and.outline")
        }
    } else {
        NavigationLink {
            Text("More!")
        } label: {
            Label("Secondary View", systemImage: "plus")
        }
    }
}
.navigationTitle("Mecurion")

Screenshot

Btw, this can be used for macOS too.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, I thought I was already trying this but I was not marking selected as optional! Wasn't clear that was what needed to happen as Xcode constantly flagged that selection: was just not available on iOS.
Yes, Xcode is not renowned for giving the most helpful error messages. Anyway, thanks for accepting the answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.