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

chr*_*ags 3 swiftui swiftui-navigationlink

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

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

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

模型结构:

struct Place: Identifiable {
var id: UUID = UUID()
var name: String = ""
var testBool: Bool = false
Run Code Online (Sandbox Code Playgroud)

}

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

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

}

导航布尔类:(生产项目这里有许多属性,我想将它们保留在一个类中)

class Navigation: ObservableObject {
@Published var showPlaceDetail: Bool = false
Run Code Online (Sandbox Code Playgroud)

}

ContentView:(NavigationView所在的父视图)

import SwiftUI
Run Code Online (Sandbox Code Playgroud)

结构ContentView:视图{

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

} // 结束结构

CardsGrid:(在此视图中,NavigationLink 不是以编程方式触发的,并且不会显示控制台错误。)

import SwiftUI
Run Code Online (Sandbox Code Playgroud)

struct CardsGrid: View { @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
Run Code Online (Sandbox Code Playgroud)

} // 结束结构

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

import SwiftUI
Run Code Online (Sandbox Code Playgroud)

结构 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
Run Code Online (Sandbox Code Playgroud)

} // 结束结构

此外:

  • 我尝试将 ForEach 包装在表单和列表中 - 不起作用。
  • 移动 ScrollView 确实有效 - 但我需要内容视图中的滚动视图,因为我还有其他视图想要滚动。
  • 我认为这可能与 LazyGrid 有关 - 也许它与 NavLink 配合得不好,但也找不到任何东西。

我怎样才能解决这个问题?

wor*_*dog 6

正如您的链接建议的那样,NavigationLinkForEach. 以下内容对我来说在 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)
    }
}
Run Code Online (Sandbox Code Playgroud)