我试图让用户控制相机硬件的设置,因此有一个设置视图和一个不同的视图,他们可以通过单击按钮选择要应用的预设。当导航回设置视图(通过 TabView)时,我希望根据单击的预设按钮显示值。但是,我发现除非单击两次按钮,否则某些UserDefault 存储的值不会被更改。
正确更新的 UserDefaults 和非工作的用户默认值之间的差异:
- 在 TextField 的设置视图中显示(并且能够更改)非工作(直到第二次点击)值,而正确工作的值被显示(并且能够要更改)由滑块。
- 非工作值默认为 Ints 并更新为 Ints,而其他值为 Floats。
我尝试过的事情:
UserDefaults.standard.setValue(values[0], forKey: "exposureISO")
UserDefaults.standard.set(Int(values[0], forKey: "exposureISO")
UserDefaults.standard.synchronize()
这是我的代码,希望能证明问题可能出在哪里:\
import SwiftUI
import Combine
struct Settings: View {
let minISO = UserDefaults.standard.integer(forKey: "minISO")
let maxISO = UserDefaults.standard.integer(forKey: "maxISO")
let maxGain = UserDefaults.standard.integer(forKey: "maxGain")
@AppStorage("exposureISO") var exposureISO = DefaultSettings.exposureISO
@State private var enteredExposureISO: String = ""
@AppStorage("redGain") var redGain = DefaultSettings.redGain
var body: some View {
ScrollView {
VStack {
TextField("", text: self.$enteredExposureISO)
.onReceive(Just(enteredExposureISO)) { typedValue in
if let newValue = Int(typedValue) {
if (newValue >= Int(minISO)) && (newValue <= Int(maxISO)) {
exposureISO = newValue
}
}
}
.textFieldStyle(.roundedBorder)
.padding()
.onAppear(perform:{self.enteredExposureISO = "\(exposureISO)"})
Slider(
value: $redGain,
in: 1...Double(maxGain),
step: 0.1
) {
Text("red Gain")
} minimumValueLabel: {
Text("1")
} maximumValueLabel: {
Text("4")
}
.padding([.leading, .trailing, .bottom])
}
}
}
}
enum DefaultSettings {
static let exposureISO = 300
static let redGain = 2.0
}
struct JobView: View {
@ObservedObject var job: Job //does this need to be observed...?
var body: some View {
VStack {
Text("Settings").fontWeight(.medium)
Text(job.settings ?? "settings not found")
.multilineTextAlignment(.trailing)
Button(action: applySettings) {
Text("Apply these settings")
}
}
}
func applySettings() {
//parse job.settings and apply the values to the camera hardware
var value = ""
var values : [Float] = []
for char in job.settings! {
if Int(String(char)) != nil || char == "." {
value.append(char)
} else if char == "\n" {
values.append(Float(value)!)
value = ""
}
}
UserDefaults.standard.set(values[0], forKey: "exposureISO")
UserDefaults.standard.set(values[1], forKey: "redGain")
}
}
如果按钮被点击两次,我发现 UserDefaults 被正确设置是最奇怪的。我感谢诊断问题以及如何解决问题的任何帮助!
编辑
就像评论中描述的和 ChrisR 建议的那样,我改为.onReceive
破解.onSubmit
/解决问题,但我还不完全理解为什么在Just(...)
点击按钮时发布者会发出。这是修复:\
TextField("", text: self.$enteredExposureISO)
.onSubmit {
if let newValue = Int(enteredExposureISO) {
if (newValue >= Int(minISO)) && (newValue <= Int(maxISO)) {
print("new value \(newValue)")
exposureISO = newValue
}
}
}
.textFieldStyle(.roundedBorder)
.padding()
.onAppear(perform:{self.enteredExposureISO = "\(exposureISO)"})