问题描述
嘿,由于状态更改或保存操作而多次调用某些SwiftUI代码是正常的吗?这段代码是一个选择器,有4个选项可供选择。然后,选定的选项通过saveBase方法保存到UserDefaults中。我在方法中添加了一条打印语句,以确认我的值正确到达,并发现每次对选择器进行更改时,该方法都会被调用19次。该代码可以很好地保存和还原baseCurr。作为具有汇编和C经验的固件工程师,我会认为这是错误的代码,但是我不确定。有什么想法吗?
class UserData: ObservableObject {
@Published var baseCurr: Int = 0
func saveBase() -> () {
let defaults = UserDefaults.standard
defaults.set(self.baseCurr,forKey: "base")
print(" base Curr = \(self.baseCurr)")
}
}
struct aboutView: View {
@EnvironmentObject var userData: UserData
let baseCurrs = ["block A","block B","block C","block D"]
var body: some View {
Form {
vstack (alignment: .leading) {
Text("Select Base")
Picker(selection: $userData.baseCurr,label: Text("Curr >")) {
ForEach(0 ..< baseCurrs.count) {
Text( baseCurrs[$0])
}
.onChange(of: userData.baseCurr) { newValue in
userData.saveBase()
}
}
}
.padding()
}
.navigationBarTitle("About",displayMode: .inline)
}
}
解决方法
正如NewDev在评论中指出的那样,您需要将onChange
修饰符附加到单个视图(例如Picker
或VStack
)而不是ForEach
。
但是,您可以通过完全删除.onChange
修饰符和saveBase()
函数来使代码更简洁。
您可以将didSet
添加到baseCurr
属性中,以在设置 时保存该值:
class UserData: ObservableObject {
@Published var baseCurr: Int = UserDefaults.standard.integer(forKey: "base") {
didSet {
UserDefaults.standard.set(baseCurr,forKey: "base")
print(" base Curr = \(baseCurr)")
}
}
}
现在您不需要onChange
:
Picker(selection: $userData.baseCurr,label: Text("Curr >")) {
ForEach(0 ..< baseCurrs.count) {
Text(baseCurrs[$0])
}
}
,
您的.onChange
被调用baseCurrs.count
次,因为您将其附加到了动态ForEach
容器上,因此.onChange
实际上附加到了每个Text(baseCurrs[$0])
上,因此可以解决为此,保留您的代码,只需要将.onChange
从动态容器中移出,例如
VStack (alignment: .leading) {
Text("Select Base")
Picker(selection: $userData.baseCurr,label: Text("Curr >")) {
ForEach(0 ..< baseCurrs.count) {
Text(baseCurrs[$0])
}
}
}
.onChange(of: userData.baseCurr) { newValue in // for eg. here !!
userData.saveBase()
}
.padding()