我有一个 SwiftUI View ,我在其中声明这样的条件
@State var condition = UserDefaults.standard.bool(forKey: "JustKey")
当我第一次将此 View 插入导航堆栈时,条件变量正在获取正确的值。然后,当我弹出此 View 时,我更改了 UserDefaults 中的值,但是当我再次按下此屏幕时,条件变量会记住它第一次获得的旧值。 如何找到解决方法,因为我想在每次进入声明它的自定义 View 时重新初始化我的条件变量?
最佳答案
在这种情况下,@State
的行为与它应该的完全一样:作为它所附加的组件的持久存储。
从根本上来说,使用 NavigationLink 推送 View 就像 View 层次结构中的任何其他组件一样。屏幕是否实际可见是一个实现细节。虽然 SwiftUI 在关闭屏幕后实际上并未渲染隐藏的 UI 元素,但它确实保留了 View
树。
您可以使用 .id(_:)
修饰符强制完全丢弃 View ,例如:
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(_:)
的单数参数发生变化时,id 修饰符告诉 SwiftUI 这是一个不同的 View ,因此当 SwiftUI 运行时,它是diffing 算法它会丢弃旧的并创建一个新的(使用新的 @State
变量)。了解有关 id 的更多信息 here .
上面的解释提供了一种解决方法,但这不是一个好的解决方案,IMO。更好的解决方案是使用 ObservableObject。它看起来像这样:
@ObservedObject condition = KeyPathObserver(\.JustKey, on: UserDefaults.standard)
您可以在 this SO answer 找到实现 KeyPathObserver
的代码和完整的 Playground 示例。
关于ios - SwiftUI @State 变量没有被取消初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59406924/