Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 保存到UserDefaults会被调用19次_Swift_Swiftui_Ios14_Userdefaults - Fatal编程技术网

Swift 保存到UserDefaults会被调用19次

Swift 保存到UserDefaults会被调用19次,swift,swiftui,ios14,userdefaults,Swift,Swiftui,Ios14,Userdefaults,嘿,一些SwiftUI代码由于状态更改或保存操作而多次被调用是正常的吗?此代码是一个选择器,可选择4个选项。然后,通过方法saveBase将所选选项保存为UserDefaults。我在方法中放入了一条print语句,以确认我的值是否正确到达,并发现每次对选择器进行更改时,该方法都会被调用19次。代码在保存和恢复baseCurr时运行良好。作为一名在汇编和C语言方面有经验的固件工程师,我认为这是一个相当错误的代码,但我不太确定。有什么想法吗 class UserData: ObservableOb

嘿,一些SwiftUI代码由于状态更改或保存操作而多次被调用是正常的吗?此代码是一个选择器,可选择4个选项。然后,通过方法saveBase将所选选项保存为UserDefaults。我在方法中放入了一条print语句,以确认我的值是否正确到达,并发现每次对选择器进行更改时,该方法都会被调用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{
@环境对象变量userData:userData
设baseCurrs=[“块A”、“块B”、“块C”、“块D”]
var body:一些观点{
形式{
VStack(对齐:。前导){
文本(“选择基”)
选择器(选择:$userData.baseCurr,标签:Text(“Curr>”){
ForEach(0..<基本货币计数){
文本(基本货币[$0])
}
.onChange(of:userData.baseCurr){newValue in
userData.saveBase()
}
}
}
.padding()
}
.navigationBarTitle(“关于”,显示模式:。内联)
}
}

正如NewDev在评论中指出的那样,您需要将
onChange
修改器附加到单个视图(如
Picker
VStack
),而不是
ForEach

但是,通过完全删除
.onChange
修饰符和
saveBase()
函数,可以使代码更干净一些

您可以将
didSet
添加到
baseCurr
属性,以便在设置值时保存该值:

现在,您不需要更改
onChange

Picker(selection: $userData.baseCurr, label: Text("Curr >")) {
    ForEach(0 ..< baseCurrs.count) {
        Text(baseCurrs[$0])
    }
}
选择器(选择:$userData.baseCurr,标签:Text(“Curr>”){
ForEach(0..<基本货币计数){
文本(基本货币[$0])
}
}

您的
.onChange
被称为
baseCurrs。计数
次,因为您将其附加到动态
ForEach
容器,所以
。onChange
实际上附加到每个
文本(baseCurrs[$0])
,所以要解决这个问题,保留您的代码,只需将
从动态容器中移出即可,像

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()
VStack(对齐:。前导){
文本(“选择基”)
选择器(选择:$userData.baseCurr,标签:Text(“Curr>”){
ForEach(0..<基本货币计数){
文本(基本货币[$0])
}
}
}
.onChange(of:userData.baseCurr){newValue in//for例如here!!
userData.saveBase()
}
.padding()

.onAppear
附加到
选择器
VStack
而不是
ForEach
我没有显示它,但是UserData init方法从UserDefaults初始化baseCurr。那么你认为iPhone缺少信号(输入)去抖动吗?嘈杂的选择器导致onChange多次调用save方法?@GalenSmith您无法将
onChange
附加到ForEach。请查看我的答案中的
UserData
版本。我去掉了onChange,并将您建议的更改添加到UserData中。它工作得很好,只更新baseCurr一次@GalenSmith我很高兴它能帮上忙:)如果你觉得我的答案解决了你的问题,你可以接受它(和/或投赞成票)-见。
Picker(selection: $userData.baseCurr, label: Text("Curr >")) {
    ForEach(0 ..< baseCurrs.count) {
        Text(baseCurrs[$0])
    }
}
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()