保存到 UserDefaults 被调用 19 次
Posted
技术标签:
【中文标题】保存到 UserDefaults 被调用 19 次【英文标题】:Save to UserDefaults Getting Called 19 Times 【发布时间】:2020-10-13 22:19:01 【问题描述】:嘿,由于状态更改或保存操作,某些 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)
【问题讨论】:
将.onAppear
附加到Picker
或VStack
而不是ForEach
【参考方案1】:
正如 NewDev 在 cmets 中指出的那样,您需要将 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])
【讨论】:
我没有展示它,但是 UserData init 方法从 UserDefaults 初始化 baseCurr。那么你认为 iPhone 中缺少信号(输入)去抖动吗?嘈杂的选择器导致 onChange 多次调用 save 方法? @GalenSmith 您只是不能将onChange
附加到 ForEach。请从我的回答中查看UserData
版本。
我摆脱了 onChange 并将您建议的更改添加到 UserData。它工作得很好,只更新一次 baseCurr!
@GalenSmith 很高兴它对您有所帮助 :) 如果您觉得我的回答解决了您的问题,您可以接受(和/或投票) - 请参阅 What should I do when someone answers my question?。【参考方案2】:
您的.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()
【讨论】:
以上是关于保存到 UserDefaults 被调用 19 次的主要内容,如果未能解决你的问题,请参考以下文章
使用 struct id 将收藏夹保存到 UserDefaults
Swift - UserDefaults 设置未保存在框架内
每次调用 .insert() 或 .remove(at:) 时,在 UserDefaults 中保存更新的 Set
UserDefaults with Struct - TableView 不显示从 UserDefaults 保存的数据?