Estoy tratando de permitir que el usuario controle la configuración del hardware de la cámara para que haya una vista de Configuración y una vista diferente donde puedan elegir ajustes preestablecidos para aplicar con solo hacer clic en un botón. Al navegar de regreso a la vista Configuración (a través de TabView), espero que los valores se muestren de acuerdo con el botón preestablecido en el que se hizo clic. Sin embargo, descubro que algunos de los valores almacenados por defecto de usuario no se cambian a menos que se haga clic en el botón dos veces.
Diferencias entre los UserDefaults correctamente actualizados y los que no funcionan:
-Los valores que no funcionan (hasta el segundo clic) se presentan (y se pueden cambiar) en la vista Configuración en un campo de texto, mientras que los valores que funcionan correctamente se presentan (y se pueden cambiar) mediante un control deslizante.
-Los valores que no funcionan son enteros por defecto y se actualizan para ser enteros, mientras que los demás son flotantes.
Cosas que he probado:
UserDefaults.standard.setValue(values[0], forKey: "exposureISO")
UserDefaults.standard.set(Int(values[0], forKey: "exposureISO")
UserDefaults.standard.synchronize()
Aquí está mi código que, con suerte, demuestra dónde podría estar el problema:\
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") } }Me parece muy extraño que los valores predeterminados del usuario se establezcan correctamente si se toca el botón dos veces. ¡Agradezco cualquier ayuda para diagnosticar el problema y cómo resolverlo!
Como se describe en los comentarios y como sugirió ChrisR, cambié .onReceive a .onSubmit para piratear/resolver el problema, pero aún no entiendo por completo por qué el editor Just(...) estaba emitiendo cuando se tocó el botón. Aquí está la solución:\
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)"})