Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default selection in sidebar navigation

Tags:

swift

swiftui

I've built a sidebar navigation on iOS/iPadOS and I'd like to preselect the first sidebar item to avoid presenting empty view on startup.

struct SidebarNavigation: View {
    enum Item: String, CaseIterable, Identifiable, Hashable {
        case inbox = "Inbox"
        case sent = "Sent"
        
        var id: String { rawValue }
        
        var destination: some View { Text(rawValue) }
    }
    
    @State var selection: Item? = .inbox
    
    var body: some View {
        NavigationView {
            List(selection: $selection) {
                ForEach(Item.allCases) { item in
                    NavigationLink(
                        destination: item.destination,
                        tag: item,
                        selection: $selection,
                        label: {
                            Text(item.rawValue)
                        })
                }
            }
            
            Text("Select Sidebar Item")
            
            Text("Detail View")
        }
    }
}

Launching this on iPad presents following even though selection is set to .inbox. I've also tried setting selection property with onAppear modifier on NavigationView, but that code only executes when tapping on Back button which produces a glitch. Is there a way to solve this or is it a SwiftUI limitation?

Sidebar navigation iPad OS

like image 556
Said Sikira Avatar asked Jul 05 '26 15:07

Said Sikira


1 Answers

The second view you pass to the NavigationView is the destination view you want to use.

I replaced the second Text with the destination view, and it now works. I also modified the destination view, to show that this isn't just the same as the NavigationLink label.

Working code:

struct SidebarNavigation: View {
    enum Item: String, CaseIterable, Identifiable, Hashable {
        case inbox = "Inbox"
        case sent = "Sent"
        
        var id: String { rawValue }
        
        var destination: some View {
            VStack {
                Text(rawValue)
                
                Text("More content...")
            }
        }
    }
    
    @State var selection: Item? = .inbox
    @State private var tableView: UITableView?
    
    var body: some View {
        NavigationView {
            List(selection: $selection) {
                ForEach(Item.allCases) { item in
                    NavigationLink(
                        destination: item.destination,
                        tag: item,
                        selection: $selection,
                        label: { Text(item.rawValue) }
                    )
                }
            }
            
            if let selection = selection {
                selection.destination
            }
            
            Text("Detail View")
        }
    }
}
like image 106
George Avatar answered Jul 07 '26 07:07

George