NavigationSplitView not working. A problem with @Binding & @State?

42 views Asked by At

I have been trying to write a simple macOS app with a three column NavigationSplitView.

I want Pension and User as structs, as well as view structs for each column, as although the app is very simple at the moment, I intend for them to become quite detailed in the future.

My code below runs, but I can't select a user or pension. I'm guessing a problem with @Binding & @State?

I expected to click the name Alice (for example) and see Pension A in column 2, then click Pension A in column 2 and see 2000 in column 3. But nothing happens when I click a name.

import SwiftUI

struct Pension: Identifiable, Hashable {
    let id = UUID()
    var pensionName: String
    var pensionValue: Double
}

struct User: Identifiable, Hashable {
    let id = UUID()
    var name: String
    var pensions: [Pension]
}

// Column 1: Users List

struct UsersListView: View {
    let users: [User]
    @Binding var selectedUser: User?
    
    
    var body: some View {
        
        List(users, selection: $selectedUser) { user in
            Text(user.name)
        }
    }
}


// Column 2: Pensions List
struct PensionsListView: View {
    let pensions: [Pension]
    @Binding var selectedPension: Pension?
    
    var body: some View {
        List(pensions, selection: $selectedPension) { pension in
            Text(pension.pensionName)
        }
    }
}

// Column 3: Pension Detail
struct PensionDetailView: View {
    var pension: Pension?
    
    var body: some View {
        if let pension = pension {
            Text("Pension Value: \(pension.pensionValue, specifier: "%.2f")")
        } else {
            Text("Select a Pension")
        }
    }
}

// Main View with NavigationSplitView

struct ContentView: View {
    @State private var selectedUser: User?
    @State private var selectedPension: Pension?
    
    // Sample data
    private var users = [
        User(name: "Alice", pensions: [Pension(pensionName: "Pension A", pensionValue: 2000.0)]),
        User(name: "Bob", pensions: [Pension(pensionName: "Pension B", pensionValue: 3000.0)])
    ]
    
    var body: some View {
        
        NavigationSplitView {
            UsersListView(users: users, selectedUser: $selectedUser)
        } content: {
            if let user = selectedUser {
                PensionsListView(pensions: user.pensions, selectedPension: $selectedPension)
            } else {
                Text("Select a User")
            }
        } detail: {
            PensionDetailView(pension: selectedPension)
        }
        .navigationSplitViewStyle(.balanced)
        
    }
}
1

There are 1 answers

0
karlb On

I found a solution. I simply had to use .tag() on my lists like so:

List(users, selection: $selectedUser) { user in
        Text(user.name).tag(user)
}
List(pensions, selection: $selectedPension) { pension in
        Text(pension.pensionName).tag(pension)
}