You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决NavigationStack中重复声明navigationDestination的控制台报错

修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 10:52:40