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

SwiftUI嵌套NavigationLink异常问题排查求助

LazyGrid中NavigationLink跳转异常问题

我使用LazyGrid展示列表项,点击元素需跳转到编辑页面,但出现以下问题:

  • 最初在ForEach中使用包含目标页的NavigationLink时,目标视图会在点击前就为每个元素完成初始化;点击后进入无限循环。移除目标视图的ViewModel后,初始化次数变为2*cList.count次。
  • 改用navigationDestination方案后,点击时目标视图会初始化cList.count次,且几乎立即自动返回,控制台报错:
    "A navigationDestination for “PEM.Category” was declared earlier on the stack. Only the destination declared closest to the root view of the stack will be used."
    

视图代码

import SwiftUI

struct ContentView2: View {
    @ObservedObject var etvm: EditTransactionViewModel
    
    var body: some View {
        NavigationStack {
            VStack{
                Form {
                    Section(header: Text("Main").font(.subheadline)){
                        NavigationLink() {
                            InnerListView2(selectedCategory: .constant(nil))
                        } label: {
                            Text("Row")
                        }
                        .isDetailLink(false)
                        .navigationTitle("Outer List")
                    }
                }
            }
        }
    }
}

struct InnerListView2: View {
    @FetchRequest (
        entity: Category.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \Category.name, ascending: true)],
        predicate: NSPredicate(format: "rootCategory == nil")
        
    ) private var cList: FetchedResults<Category>
    
    @Binding var selectedCategory: Category?
    
    var body: some View {
        Form {
            Section(header: Text("Root Categories").font(.subheadline)) {
                ScrollView {
                    LazyVGrid(columns: [GridItem(.flexible())], spacing: 20) {
                        ForEach(cList, id: \.self) { c in
//     OPTION 2                               NavigationLink(value: c) {
//                                        SelectableCategoryView(category: c, showEdit: true)
//                                    }
                                NavigationLink(destination: InnerInnerListView2(ecvm: .init(category: c))) {
                                    SelectableCategoryView(category: c, showEdit: true)
                                }
                                .isDetailLink(false)
                                .navigationTitle("Inner List")
                               
                            }
                        }
//   OPTION 2                 .navigationDestination(for: Category.self) { c in
//                            InnerInnerListView2(ecvm: .init(category: c)
//                        }
                    
                }
            }
        }
    }
}

struct InnerInnerListView2: View {
    @ObservedObject var ecvm: EditCategoryViewModel
    
    var body: some View {
        Text("Row \(ecvm.wrappedCat.iconName) " )
    }
}


struct ContentView2_Previews: PreviewProvider {
    static var previews: some View {
        ContentView2(etvm: .init())
    }
}

ViewModel代码

@MainActor class EditCategoryViewModel: ObservableObject {
        var storedCat: Category?
        @Published var wrappedCat: InputCatModel
        
        @Published var hasError = false
        
        let isNew: Bool
        private let provider = PersistenceController.shared
        
        init(category: Category? = nil, in context: NSManagedObjectContext = PersistenceController.shared.container.viewContext) {
            
            print("Eccomi")
            
            self.storedCat = category
            
            if let category, let existingObj = provider.exisits(category, in: context) as? Category {
                self.wrappedCat = .init(category: existingObj)
                self.isNew = false
            } else {
                self.wrappedCat = .init()
                self.isNew = true
            }
            
        }
        
    }

测试代码

@main
struct testApp: App {
    let persistenceController = PersistenceController.shared

    var body: some Scene {
        WindowGroup {
            ContentView2(etvm: .init())
                .environment(\.managedObjectContext, persistenceController.container.viewContext)
                .onAppear(perform: { setDefCategories(persistenceController.container.viewContext) })
            
    }
    
    func setDefCategories(_ viewContext: NSManagedObjectContext) {
        
        // MARK: Root Category
        
        let e1 = Category(context: viewContext)
        e1.name = "Generico"
        e1.icon = "cart"
        e1.isIncome = false
        e1.rootCategory = nil
        e1.colorId = "IconColor1"
        
        let e2 = Category(context: viewContext)
        e2.name = "Spesa ed Alimenti"
        e2.icon = "cart"
        e2.isIncome = false
        e2.rootCategory = nil
        e2.colorId = "IconColor2"
    }
}

内容的提问来源于stack exchange,提问作者FeroX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:07:14