SwiftUI @State变量未初始化

问题描述 投票:0回答:1

我有一个SwiftUI View,我在其中声明了这样的条件

@State var condition = UserDefaults.standard.bool(forKey: "JustKey")

[当我第一次将此视图推入导航堆栈时,条件变量获取正确的值。然后,当我弹出该视图时,我更改了UserDefaults中的值,但是当我再次按下此屏幕时,条件变量会记住它第一次获得的旧值。如何找到解决方法,因为每次我进入声明它的自定义视图时都想重新初始化条件变量?

ios swift xcode swiftui combine
1个回答
0
投票
在这种情况下,@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示例。>
© www.soinside.com 2019 - 2024. All rights reserved.