SwiftUI 中嵌套的 navigationDestination 无限循环

Jef*_*eff 8 swiftui

我读过很多关于 SwiftUI 中无限循环的其他问题和答案。我的问题是不同的,虽然也许这个错字问题是相关的,但我不这么认为。

我已将问题缩小到:在 a 中,在目标闭包中使用与数据类型不同的可识别类型的NavigationStack较低级别在上层目标闭包中创建无限循环。navigationDestinationfornavigationDestination

我花了几个小时来减少和抽象重新创建代码。这是我能做到的最浓缩的。当我进一步简化时,无限循环消失了,但我还无法确定原因。例如,我创建了一个单层NavigationStack(未显示),其中目标闭包不使用for数据类型,但它可以正常工作。

struct F3: Identifiable, Hashable {
    let id: String = UUID().uuidString
    let t: String
}
struct R3: Identifiable, Hashable {
    let id: String = UUID().uuidString
    let t:String
}
struct N3: Identifiable, Hashable {
    let id:String = UUID().uuidString
    let t: String
}
struct LV3: View { // Use `App` conformer to load this View in WindowGroup.
    let f2z = [ F3(t: "A"), F3(t: "B"),]
    
    var body: some View {
        NavigationStack {
            List(f2z) { f in
                NavigationLink(f.t, value: f)
            }
            .navigationDestination(for: F3.self) { f in
                VV3() // Infinite loop here.
            }
            .navigationTitle("L")
        }
    }
}
struct VV3: View {
    let r = R3(t: "rrr")
    let nz: [N3] = [
        N3(t: "hhh"),
        N3(t: "ttt"),
    ]
    var body: some View {
        List(nz) {
            NavigationLink($0.t, value: $0)
        }
        .navigationDestination(for: N3.self) { n in
            Text(r.t) // Changing to String literal or `n.t` fixes the infinite loop.
        }
        .navigationTitle("V")
    }
}
Run Code Online (Sandbox Code Playgroud)

Alb*_*bin 5

也许我参加聚会有点晚了,但我最近在一个项目中遇到了同样的问题,其中每个视图都有一个我在 .navigationDestination(...) 中使用的 ViewModel 对象。有时会导致无限循环,但并非每次都会。我们引入的规则是不要在 .navigationDestination(...) 函数中引用视图所依赖的任何对象。应用此规则后似乎有效。

这不起作用:

@StateObject var viewModel: ViewModel

var body: some View {
    Text("Some View")
        .navigationDestination(for: Routing.self) { route in
            switch route {
                case .showMap:
                    MapView(viewModel.someValue)
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

这似乎有效:

@StateObject var viewModel: ViewModel

var body: some View {
    Text("Some View")
        .navigationDestination(for: Routing.self) { route in
            switch route {
                case .showMap(let someValue):
                    MapView(someValue)
            }
        }
}
Run Code Online (Sandbox Code Playgroud)