swiftui navigationLink is not working when nested

47 Views Asked by At

Here I want to make sections in side the navigation SideBar of a NavigationSplitView. If I add sections the links are not working anymore, The view is not opening inside the detail view; why and how to solve this?

I use this as sample code to show what goes wrong.

import SwiftUI

enum Navigation2: String, Hashable, CaseIterable {
    case bike = "Fiets"
    case car = "Bak Met Wielen"
    case bus = "Komt zo"
    
    static let allNavigationCases = Navigation.allCases.map { $0.rawValue }
    
}

struct MainNavigationSplitView: View {
    @State private var selection: String? 
    
    var body: some View {
        NavigationSplitView {
            // Sidebar view
            Text("Nav").bold()
            // **next two line gives issues and make the navigtionlink not working**
            ForEach (Navigation2.allNavigationCases, id: \.self) { section in
                Section(section ){
                    List(selection: $selection) {
                        NavigationLink(value: section) {
                        Label("View 3", systemImage: "3.circle")
                    }
                        NavigationLink(destination: View1(), tag: "View1", selection: $selection) {
                            Label("View 1", systemImage: "1.circle")
                        }
                        NavigationLink(destination: View2(), tag: "View2", selection: $selection) {
                            Label("View 2", systemImage: "2.circle")
                        }
                        NavigationLink(destination: View3(), tag: "View3", selection: $selection) {
                            Label("View 3", systemImage: "3.circle")
                        }
                    }
                    .listStyle(SidebarListStyle())
                    .frame(minWidth: 200)
                    .navigationTitle("Sidebar")
               } header: {
                    Text("Navigable rows \(section)")
                }
            }
        } detail: {
            // Detail view
            if let selection = selection {
                Text("This is the detail view for \(selection)")
                    .navigationTitle(selection)
            } else {
                Text("Please select something from the sidebar")
                    .foregroundColor(.gray)
            }
        }
    }
}

// first type of view
struct View1: View {
    var body: some View {
        Text("This is view 1")
            .navigationTitle("View 1")
    }
}

// second type of view
struct View2: View {
    var body: some View {
        Text("This is view 2")
            .navigationTitle("View 2")
    }
}

// second type of view
struct View3: View {
    var body: some View {
        Text("This is view 3")
            .navigationTitle("View 3")
    }
}

What should I do to use sections? If I use that as showed sometimes it works when other sections are closed. If more then one is open the links doesn't work.The views are just examples to show what is going wrong. Thank you

1

There are 1 best solutions below

0
iPadawan On

There where more semi issues then using the old way of the NavigationLink.

This partly the way I want to go and it works for now.

struct MyNavigationView: View {
    enum Category: String, Hashable, CaseIterable, Identifiable  {
        var id: Self {
            return self
        }
        
        case section_1 = "Section 1"
        case section_2 = "Section 2"
        case section_3 = "Section 3"
        
        static let allCategories = Category.allCases.map { $0.rawValue }
        
        func getArray() -> [Item] {
            switch self {
            case .section_1:
                return Array(MyNavigationView().section1)
            case .section_2:
                return Array(MyNavigationView().section2)
            case .section_3:
                return Array(MyNavigationView().section3)
            }
            
        }
    }
    
    let section1 = items[0...2]
    let section2 = items[3...5]
    let section3 = items[6...8]
    
    @State var selectedItem: Item?
    
    var body: some View {
        NavigationSplitView () {
            List {
                ForEach(Category.allCases, id: \.self){ category in
                    Section(header: Text(category.rawValue).font(.title2)) {
                        ForEach(category.getArray(), id: \.self) { item in
                            NavigationLink(value: item,
                                           label: { Text(item.name)
                            })
                        }
                    }
                }
            }
                    .listStyle(SidebarListStyle())
                    .navigationDestination(for: Item.self) { value in
                        DetailView(item: value)
                        Text(value.id.uuidString)
                            .navigationTitle("Detail View")
                    }
                    .navigationSplitViewColumnWidth(min: 100, ideal: 150, max: 200)
        }detail: {
            // Use a placeholder view for the detail area when no item is selected
            if selectedItem != nil {
                Text("selected \(selectedItem!.name)")
                
            } else {
                Text("Select an item ")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
        }
    }
}

struct ContentView: View {
    var body: some View {
        MyNavigationView()
    }
}

using the following data

struct Item: Identifiable, Hashable {
    var id = UUID()
    var name: String
    var place: String
    var date: Date
}

let items = [
    Item(name: "Alice", place: "Wonderland", date: Date()),
    Item(name: "Bob", place: "Bikini Bottom", date: Date()),
    Item(name: "Charlie", place: "Chocolate Factory", date: Date()),
    Item(name: "David", place: "Dungeon", date: Date()),
    Item(name: "Eve", place: "Eden", date: Date()),
    Item(name: "Frank", place: "France", date: Date()),
    Item(name: "Grace", place: "Greece", date: Date()),
    Item(name: "Harry", place: "Hogwarts", date: Date()),
    Item(name: "Iris", place: "Italy", date: Date()),
    Item(name: "Jack", place: "Japan", date: Date())
]

struct DetailView: View {
    var item: Item
    
    var body: some View {
        VStack {
            // Use the item's name as the title of the view
            Text(item.name)
                .font(.largeTitle)
                .bold()
            Text(item.place)
                .font(.title)
            Text(item.date, style: .date)
                .font(.title2)
        }
    }
}

I place it here in case some one may need it. Of course if someone can simplify this don't hold your horses.