SwiftUI:导航链接选择器在渲染之间不持久

我正在尝试将其拔掉,以进行解释,它的设置时间很长(除了不确定导致该行为的因素之外,没有其他原因),请耐心等待。这是设置:

  1. I want to persist some navigation link choices the user makes so I can edit them in the future, for this I create an ObservableObject which stores a path (selectedPath) (ref: 1 - Screen Navigator)
  2. I want to update the ScreenNavigator when the user clicks a certain NavigationLink (ref: 2 - Main View). This essentially saves the users choice. This works absolutely fine on the first selection of a link.
  3. The FooView renders several more views which may need to manipulate the environment injected ScreenNavigator (ref: 3 - A Few More Views), some of them may call APIs that trigger the other observed objects in the Main View causing a re-render.

问题

Point 3 is where the main issue occurs, when QuxView calls a function which manipulates state, the state object of FooView has a change triggered which causes a rerender. However, the previously set selectedPath from the injected screenNavigator object in the FooView becomes nil and the user selection is lost. QuxView still successfully renders (and all the navigation views along the way are traversable). Its just the screenNavigator that seems to lose its value.

Does anyone know what causes the selectedPath to now be nil and what I would do to instead persist it?

1-屏幕导航器:

final class ScreenNavigator: ObservableObject {
    @Published var selectedPath: String?
}

2-主视图(主视图):

// 1. This is the initial view, it has a state ObservedObject that likes to change a lot
// and a screen navigator that is provided alongside it.
struct FooView: View {
    @ObservedObject var state = StateObservable()
    @EnvironmentObject var screenNavigator: ScreenNavigator

    var body: some View {
        NavigationView {
            ForEach(state.foos) { foo in
                NavigationLink(
                    destination: BarView(bars: foo.bars),
                    tag: "foo:\(foo.id)",
                    selection: self.$screenNavigator.selectedPath
                ) {
                    Text(foo.name)
                }
            }
        }
    }
}

此时,没有什么太普通的了,用户选择的标签是通过绑定的屏幕导航器设置的。但是,当我们添加其他触发重新渲染的视图时,事情似乎变得更加棘手。

3-其他视图

// 2. This is a secondary navigation link, typically on the first render of this view
// the ScreenNavigator.selectedPath has a value
struct BarView: View {
    let bars: [Bar]

    var body: some View {
        List(bars) { bar in
            NavigationLink(
                destination: QuxView(qux: bar.qux) // we went straight to qux, insane
            ) {
                Text(bar.name)
            }
        }
    }
}

struct QuxView: View {
    // this initialization has a side effect that causes the FooView.state to trigger a change
    // this may seem unnecessary in the larger schemes this is just an API call that
    // adds stored state that `FooView.state` will trigger on
    let stateManipulator = StateManipulator()

    var body: some View {
        ...
    }
}

如果有人遇到类似问题,或者知道为什么重新提交会导致此问题,请告诉我。