Home > Blockchain >  Swift: How to change DetailView depending on SideBar Selection State with SwiftUI 4?
Swift: How to change DetailView depending on SideBar Selection State with SwiftUI 4?

Time:07-11

Context

I have a problem with the new SwiftUI SideBar / NavigationLink concept. I have created a simple 2 Column NavigationSplitView with a SideBar and a DetailView.

Once the App is launched, the preselected Timeline RootView appears as the DetailView. However, when I select a different SideBar Item, the DetailView does not change accordingly.


Code

struct SideBar: View {
    @State private var navigationItem: NavigationItem? = .timeline
    
    var body: some View {
        NavigationSplitView {
            List(NavigationItem.allCases, id: \.self, selection: $navigationItem) { navigationItem in
                NavigationLink(value: navigationItem) {
                    Label(navigationItem.name, systemImage: navigationItem.symbol)
                }
            }
        } detail: {
            if let safeNavigationItem = navigationItem {
                safeNavigationItem.rootView
            } else {
                Text(String(localized: "select.an.option", defaultValue: "Select an Option"))
            }
        }
    }
}

enum NavigationItem: CaseIterable {
    case item1
    case item2
    case item3
    case item4
    
    var name: String {
        switch self {
        case .item1: return "Item 1"
        case .item2: return "Item 2"
        case .item3: return "Item 3"
        case .item4: return "Item 4"
        }
    }
    
    var symbol: String {
        switch self {
        case .item1: return "1.square.fill"
        case .item2: return "2.square.fill"
        case .item3: return "3.square.fill"
        case .item4: return "4.square.fill"
        }
    }
    
    @ViewBuilder var rootView: some View {
        switch self {
        case .item1: Text("Item 1")
        case .item2: Text("Item 2")
        case .item3: Text("Item 3")
        case .item4: Text("Item 4")
        }
    }
}

Question

Do you have any idea how I can solve this issue? Thanks a lot for your support in advance.

Note: Just ran it on macOS, it is working there. However, still not working on iPadOS.

CodePudding user response:

It looks like they forgot (or got broken) ViewBuilder for detail: part. It worth submitting feedback to Apple.

A safe workaround is to wrap conditional block into some stack, like

    } detail: {
        VStack {      // << here !!
            if let safeNavigationItem = navigationItem {
                safeNavigationItem.rootView
            } else {
                Text(String(localized: "select.an.option", defaultValue: "Select an Option"))
            }
        }
    }

Tested with Xcode 14b3 / iOS 16

  • Related