SwiftUI NavigationLink 控制台错误(SwiftUI 在推送 NavigationLink 时遇到问题。请提交错误。)

SwiftUI NavigationLink Console Error (SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug.)

尝试以编程方式触发导航时遇到上述错误问题Link。单击 link 后,将偶尔加载错误的目标数组元素(与单击的标签相比),当然会显示上述错误。

当我以非编程方式触发导航 Link 时,不会发生错误,但是当用户单击此 link 时,我需要使用另一种方法 运行。

我已经阅读了几个问题,例如 here and here,但找不到我的原因。

模型结构:

struct Place: Identifiable {
var id: UUID = UUID()
var name: String = ""
var testBool: Bool = false

}

Class 对于环境对象:(生产项目有许多属性和方法 - 本质上这是 ViewModel)

class UserPlaces: ObservableObject {
@Published var placesArray: [Place] = [Place]([Place(name: "Christian", testBool: false),Place(name: "Catherine", testBool: true)])

}

Class 用于导航布尔值:(生产项目在这里有许多我想保留在一个属性中的属性 class)

class Navigation: ObservableObject {
@Published var showPlaceDetail: Bool = false

}

ContentView:(NavigationView所在的父视图)

import SwiftUI

构造 ContentView:视图 {

var body: some View {
    
    NavigationView {
        
        ScrollView {
            
            Text("Hello, world!")
                .padding()
            CardsGrid2()
            
        } // End ScrollView
    } // End Navigation View
} // End body

} // 结束结构

CardsGrid:(在此视图中,导航Link 未以编程方式触发,控制台错误未显示。)

import SwiftUI

构造 CardsGrid:查看 { @EnvironmentObject var userPlaces: UserPlaces

var gridLayout: [GridItem] = [GridItem(.flexible(minimum: 40), spacing: -36),GridItem(.flexible(minimum: 40), spacing: -36)]

var body: some View {
    
    LazyVGrid(columns: gridLayout, spacing: 10) {
        
        ForEach(userPlaces.placesArray) { placeCard in
                
            NavigationLink(
                destination: Text("Destination")
                , label: { Text("Label") }
            )

        } // End ForEach
    
    } // End LazyVGrid
} // End body

} // 结束结构

CardsGridProgrammatic:(在此视图中,导航Link 以编程方式触发并显示控制台错误。)

import SwiftUI

构造 CardsGridProgrammatic:视图 {

@EnvironmentObject var userPlaces: UserPlaces
@EnvironmentObject var navigation: Navigation

var gridLayout: [GridItem] = [GridItem(.flexible(minimum: 40), spacing: -36),GridItem(.flexible(minimum: 40), spacing: -36)]

var body: some View {
    
    LazyVGrid(columns: gridLayout, spacing: 10) {
        
        ForEach(userPlaces.placesArray) { placeCard in
            NavigationLink(destination: Text("Destination"), isActive: $navigation.showPlaceDetail) { EmptyView() }
            .isDetailLink(false)

                    Button(action: {

                        navigation.showPlaceDetail = true
                        // Other required method call here

                    }, label: { Text("label") })

        } // End ForEach
    
    } // End LazyVGrid
    
} // End body

} // 结束结构

此外:

我该如何解决这个问题?

按照您的链接建议将 NavigationLink 移出 ForEach。 以下在 macos 12.01、xcode 13.1、目标 ios 15 和 macCatalyst 12 上对我来说效果很好。 在 mac Monterey 和 iPhone ios 15 台设备上进行了测试。在旧系统上可能有所不同。 可以肯定的是,这是我用来测试的代码:

import SwiftUI

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct Place: Identifiable {
    var id: UUID = UUID()
    var name: String = ""
    var testBool: Bool = false
}

class UserPlaces: ObservableObject {
    @Published var placesArray: [Place] = [
        Place(name: "Christian", testBool: false),
        Place(name: "Catherine", testBool: true)]
}

class Navigation: ObservableObject {
    @Published var showPlaceDetail: Bool = false
}


struct ContentView: View {
    @StateObject var userPlaces = UserPlaces()
    @StateObject var navigation = Navigation()
    
    var body: some View {
        NavigationView {
            ScrollView {
                Text("Hello, world!").padding()
                CardsGrid()
            }
        }
        .environmentObject(userPlaces)
        .environmentObject(navigation)
    }
}

struct CardsGrid: View {
    @EnvironmentObject var userPlaces: UserPlaces
    @EnvironmentObject var navigation: Navigation
    
    @State var selection: Place?  // <--- here
    
    var gridLayout: [GridItem] = [GridItem(.flexible(minimum: 40), spacing: -36),
                                  GridItem(.flexible(minimum: 40), spacing: -36)]
    
    var body: some View {
        LazyVGrid(columns: gridLayout, spacing: 10) {
            ForEach(userPlaces.placesArray) { placeCard in
                Button(action: {
                    selection = placeCard   // <--- here
                    navigation.showPlaceDetail = true
                    // Other required method call here
                }, label: { Text("\(placeCard.name) label") })
            }
        }
        // --- here
        NavigationLink(destination: Text("Destination \(selection?.name ?? "")"),
                       isActive: $navigation.showPlaceDetail) { EmptyView() }.isDetailLink(false)
    }
}