我觉得我一定做了什么蠢事。我所要做的就是从UserDefaults中拉出一个Picker值,然后在Picker改变时保存到UserDefaults。当我尝试让代码在iOS14和ios15上工作时,我遇到了这个问题。
struct SettingsView: View {
@State var rangeSelection: Int = UserDefaults.standard.integer(forKey: "vocalRange")
@State var rangeOptions = ["Soprano", "Mezzo-Soprano/Alto", "Extended Range"]
var body: some View {
VStack{
Form {
Section {
Picker(selection: $rangeSelection, label: Text("Range")) {
ForEach(0 ..< rangeOptions.count, id: .self) { range in
Text(rangeOptions[range])
.tag(range)
}
}
.onChange(of: rangeSelection, perform: { value in
UserDefaults.standard.setValue(rangeSelection, forKey: "vocalRange")
})
}
}
}
.navigationTitle("Settings")
.navigationBarTitleDisplayMode(.inline)
}
}
这似乎工作得很好,和'onChange'火很好。唯一奇怪的是,如果你离开页面并立即返回,'rangeSelection'变量重置为它最初的值。然而,一旦你重新启动应用程序,更改就会正确地反映出来。
作为替代方案,我尝试了以下
@State var rangeSelection: Int = 0
...
.onAppear(perform:{
rangeSelection = UserDefaults.standard.integer(forKey: "vocalRange")
})
这产生了另一个有趣的问题。在iOS15中它工作得很好,但在iOS14中,一旦你改变了选择器,OnAppear会在OnChange之前触发,并将选择器恢复到之前的值。这只是因为我在表单/列表中使用选择器,所以当你选择选择器时它会改变页面。
我觉得我应该使用一个明显的解决方案。
感谢@loremipsum,我使用了AppStorage。我像这样声明变量,不需要'onChange' !
@AppStorage("vocalRange") var rangeSelection: Int = UserDefaults.standard.integer(forKey: "vocalRange")
你可以在。onappear方法中设置延迟来工作
.onAppear(perform:{
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
rangeSelection = UserDefaults.standard.integer(forKey: "vocalRange")
}
})