我有一个SwiftUI View,我在其中声明了这样的条件
@State var condition = UserDefaults.standard.bool(forKey: "JustKey")
[当我第一次将此视图推入导航堆栈时,条件变量获取正确的值。然后,当我弹出该视图时,我更改了UserDefaults中的值,但是当我再次按下此屏幕时,条件变量会记住它第一次获得的旧值。如何找到解决方法,因为每次我进入声明它的自定义视图时都想重新初始化条件变量?
@State
的行为与预期的完全相同:作为其所附加组件的持久存储。在操场上尝试一下:let x = NavigationLink(destination: DetailView()) {
Text("Show Detail View")
}
print(type(of: x))
输出为:
NavigationLink<Text, DetailView>
从根本上讲,使用NavigationLink推送视图就像视图层次结构中的任何其他组件一样。屏幕是否实际可见是实现细节。尽管SwiftUI在关闭屏幕后并没有真正呈现隐藏的UI元素,但它确实保留了组件树。 (详细了解SwiftUI的静态类型here)您可以使用
.id(_:)
修饰符强制将视图完全抛弃,例如:
struct ContentView: View { @State var i = 0 var body: some View { NavigationView { VStack { NavigationLink(destination: DetailView().id(i)) { Text("Show Detail View") } Button("Toggle") { self.i += 1 UserDefaults.standard.set( !UserDefaults.standard.bool(forKey: "JustKey"), forKey: "JustKey") } } } } }
切换按钮既可以修改JustKey的值,又可以增加传递给
.id(i)
的值。 id修饰符告诉SwiftUI 这是一个不同的视图,因此,在SwiftUI运行它的差异算法时,它将丢弃旧的并创建一个新的(带有新的@State
变量)。进一步了解id here。
以上说明提供了一种解决方法,但IMO不是一个很好的解决方案。更好的解决方案是使用ObservableObject
。看起来像这样:
@ObservedObject condition = KeyPathObserver(\.JustKey, on: UserDefaults.standard)
您可以在KeyPathObserver
处找到实现this SO answer的代码和完整的Playground示例。>