Posts

Post not yet marked as solved
6 Replies
1.2k Views
I've seen several posts regarding NavigationStack in a NavigationSplitView. All had specific issues and some were marked as resolved. I couldn't get any of the suggested solutions working on macOS so I'll present some stripped down examples, all part of FB11842563: 1. Sidebar Selection struct SidebarSelection: View {     @State var selection: Int?     @State var path: [Int] = []     var body: some View {         NavigationSplitView {             List(1...20, id: \.self, selection: $selection) { number in                     Text("I like \(number)")             }         } detail: {             NavigationStack(path: $path) {                 VStack {                     Image(systemName: "x.squareroot")                         .imageScale(.large)                         .foregroundColor(.accentColor)                     Text("This is the NavigationStack root")                 }                 .padding()                 .navigationDestination(for: Int.self) { number in                     Text("You chose \(number)")                 }             }         }         .onChange(of: selection) { newValue in             print("You clicked \(newValue)")             if let newValue {                 path.append(newValue)             }         }         .onChange(of: path) { newValue in             print("Path changed to \(path)")         }     } } If we run this and click: „I like 5“ „I like 6“ „I like 7“ We would expect the detail view to show: „You chose 5“ „You chose 6“ „You chose 7“ And the console to show: You clicked Optional(5) Path changed to [5] You clicked Optional(6) Path changed to [5, 6] You clicked Optional(7) Path changed to [5, 6, 7] What we actually see in the detail view is: „You chose 5“ „This is the NavigationStack root“ „You chose 7“ And the console shows: Update NavigationRequestObserver tried to update multiple times per frame. You clicked Optional(5) Path changed to [5] You clicked Optional(6) Path changed to [] You clicked Optional(7) Path changed to [7] 2. Sidebar and Stack Selection Now we copy the list to the navigationDestination: struct SidebarAndStackSelection: View {     @State var selection: Int?     @State var path: [Int] = []     var body: some View {         NavigationSplitView {             List(1...20, id: \.self, selection: $selection) { number in                     Text("I like \(number)")             }         } detail: {             NavigationStack(path: $path) {                 VStack {                     Image(systemName: "x.squareroot")                         .imageScale(.large)                         .foregroundColor(.accentColor)                     Text("This is the NavigationStack root")                 }                 .padding()                 .navigationDestination(for: Int.self) { number in                     VStack {                         Text("You chose \(number)")                         List(1...20, id: \.self, selection: $selection) { number in                             Text("I like \(number)")                         }                     }                 }             }         }         .onChange(of: selection) { newValue in             print("You clicked \(newValue)")             if let newValue {                 path.append(newValue)             }         }         .onChange(of: path) { newValue in             print("Path changed to \(path)")         }     } } We repeat our test from above, clicking either on the sidebar or in the detail view and we expect the same outcome. This time the detail view shows the expected screen and the path is not completely wiped out but it is also not appended: Update NavigationRequestObserver tried to update multiple times per frame. You clicked Optional(5) Path changed to [5] You clicked Optional(6) Path changed to [6] You clicked Optional(7) Path changed to [7] 3. Sidebar and Stack Selection, initialized Same as before, but now we initialize the view with a non-empty path: SidebarAndStackSelection(path: [1]) The app freezes on launch, CPU is at 100 percent and the console shows only: Update NavigationRequestObserver tried to update multiple times per frame. Update NavigationRequestObserver tried to update multiple times per frame. The SwiftUI instruments seem to show heavy activity of the Stack and the SplitView: 4. Selection only in Stack Once we remove the selection from the sidebar everything works as expected (adding the NavigationStack to the root view to be able to click on a number): struct SidebarWithoutSelectionButStack: View {          @State var selection: Int?     @State var path: [Int] = []          var body: some View {         NavigationSplitView {             List(1...20, id: \.self) { number in                     Text("I like \(number)")             }         } detail: {             NavigationStack(path: $path) {                 List(1...20, id: \.self, selection: $selection) { number in                     Text("I like \(number)")                 }                 .padding()                 .navigationDestination(for: Int.self) { number in                     VStack {                         Text("You chose \(number)")                         List(1...20, id: \.self, selection: $selection) { number in                             Text("I like \(number)")                         }                     }                 }             }         }         .onChange(of: selection) { newValue in             print("You clicked \(newValue)")             if let newValue {                 path.append(newValue)             }         }         .onChange(of: path) { newValue in             print("Path changed to \(path)")         }     } } Problem of course is, that now the sidebar is useless.
Posted Last updated
.