如何解决NavigationStack中重复声明navigationDestination的控制台报错
你的Expenses视图功能正常,但控制台出现重复声明导航目标的报错:
A navigationDestination for “Cost_Control.Movement” was declared earlier on the stack. Only the destination declared closest to the root view of the stack will be used
问题根源
你把针对Movement类型的navigationDestination放在了ForEach循环的列表项内部,这会导致每生成一行列表,就重复声明一次该类型的导航目标,触发控制台报错。另外,工具栏按钮的navigationDestination放在toolbar内部也不符合最佳实践。
修复方案
把所有navigationDestination统一移到NavigationStack的直接子视图层级(比如List的外部,和导航标题、工具栏同级的位置),确保同类型的导航目标只声明一次:
修改后的完整代码:
struct Expenses: View { @Environment(\.modelContext) private var modelContext var dm : DataManager @Query(animation: .snappy) var movments : [Movement] @State var addMovments = false var body: some View { NavigationStack{ List{ ForEach(filter(array: movments),id:\.0){ dt in Section("\(dt.0)", isExpanded: .constant(true)) { ForEach(dt.1) { item in NavigationLink(value: item) { HStack{ VStack(alignment:.leading){ Text(item.title) } .lineLimit(1) Spacer(minLength: 5) Text(item.ammountString) .font(.title3.bold()) } } // 移除这里的navigationDestination } } } } .navigationTitle("Movements") .toolbar(content: { Button(action: { addMovments.toggle() }, label: { Image(systemName: "plus.circle.fill") .font(.title3) }) // 移除这里的navigationDestination }) // 统一声明所有导航目标 .navigationDestination(for: Movement.self) { mov in Text("Details of \(mov.title) - \(mov.ammount)") } .navigationDestination(isPresented: $addMovments, destination: { AddMovments(dm:dm, addMovments: $addMovments) }) } } func filter(array: [Movement])->[(String, [Movement])] { let dict = Dictionary(grouping: array, by: { $0.dateString }) let sort = dict.sorted(by: { $0.key < $1.key }) return sort } }
说明
NavigationStack要求同一类型的导航目标只能声明一次,且应放在靠近根视图的位置。这样所有对应类型的NavigationLink都会复用这个唯一的导航目标,既解决了报错问题,也符合SwiftUI导航的设计规范。
内容的提问来源于stack exchange,提问作者Damiano Miazzi
相关产品推荐
相关产品推荐

