• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

193
Views
Observe los cambios en NumberFormatter en SwiftUI TextField

Estoy creando una aplicación para macOS en la que tengo un objeto Formatter observable que usa @AppStorage para almacenar la configuración de dígitos significativos (ver Formatter.swift ). El formateador de números se pasa a las otras vistas como un objeto de entorno utilizando la estructura principal de la aplicación MyApp.swift . En la ventana de preferencias SettingsView.swift , los dígitos significativos se ajustan mediante escaladores. Finalmente, el formateador de números se asigna a los campos de texto en ContentView.swift para formatear la entrada.

El problema es que los campos de texto en la vista de contenido no actualizan automáticamente su formato cuando se cambian los dígitos significativos en la vista de configuración. Las etiquetas de texto se actualizan automáticamente porque leen los valores de almacenamiento de la aplicación directamente. Pero los campos de texto no observan el cambio en el formateador de números. Si cambio la configuración, reinicio la aplicación, los campos de texto mostrarán correctamente el formato actualizado. Pero, ¿cómo le digo al campo de texto que se actualice cuando cambien los dígitos significativos del formateador?

ventanas de aplicaciones

Formateador.swift

 import Foundation import SwiftUI class Formatter: ObservableObject { @AppStorage("minSigDigits") var minSigDigits = 1 @AppStorage("maxSigDigits") var maxSigDigits = 6 var numberFormatter: NumberFormatter { let formatter = NumberFormatter() formatter.numberStyle = .decimal formatter.usesSignificantDigits = true formatter.minimumSignificantDigits = self.minSigDigits formatter.maximumSignificantDigits = self.maxSigDigits return formatter } func resetValues() { self.minSigDigits = 1 self.maxSigDigits = 6 } }

MiAplicación.swift

 import SwiftUI @main struct MyApp: App { @StateObject var formatter = Formatter() var body: some Scene { WindowGroup { ContentView().environmentObject(formatter) } Settings { SettingsView().environmentObject(formatter) } } }

ContentView.swift

 import SwiftUI struct ContentView: View { @State private var min: Double = 0.0 @State private var max: Double = 1.0 @EnvironmentObject var formatter: Formatter var body: some View { VStack { Text("Min Sig. Digits = \(formatter.minSigDigits)") TextField("enter min value", value: $min, formatter: formatter.numberFormatter) Text("Max Sig. Digits = \(formatter.maxSigDigits)") TextField("enter max value", value: $max, formatter: formatter.numberFormatter) } .padding() .frame(width: 400, height: 300) } }

SettingsView.swift

 import SwiftUI struct SettingsView: View { @EnvironmentObject var formatter: Formatter var body: some View { VStack { Stepper("Min Significant Digits: \(formatter.minSigDigits)", value: $formatter.minSigDigits, in: 1...5) Stepper("Max Significant Digits: \(formatter.maxSigDigits)", value: $formatter.maxSigDigits, in: 6...10) Button("Reset Values") { formatter.resetValues() } } .padding() .frame(width: 300, height: 200) } }
over 3 years ago · Santiago Trujillo
2 answers
Answer question

0

Agregue un .id a TextFields, que forzará un redibujado en el cambio:

 Text("Min Sig. Digits = \(formatter.minSigDigits)") TextField("enter min value", value: $min, formatter: formatter.numberFormatter) .id(formatter.minSigDigits) Text("Max Sig. Digits = \(formatter.maxSigDigits)") TextField("enter max value", value: $max, formatter: formatter.numberFormatter) .id(formatter.maxSigDigits)

EDITAR: ... o establecer un .id en la vista completa para volver a dibujar todo:

 VStack { Text("Min Sig. Digits = \(formatter.minSigDigits)") TextField("enter min value", value: $min, formatter: formatter.numberFormatter) Text("Max Sig. Digits = \(formatter.maxSigDigits)") TextField("enter max value", value: $max, formatter: formatter.numberFormatter) } .id(formatter.maxSigDigits + formatter.minSigDigits)

La lógica básica es que, cada vez que cambie la identificación, SwiftUI volverá a dibujar esa parte.

over 3 years ago · Santiago Trujillo Report

0

Su formatter.numberFormatter getter está creando un objeto cada vez (en realidad, 2 objetos porque se llama dos veces) se llama en el cuerpo, no puede hacer eso en SwiftUI. El cuerpo debe ser rápido porque se llama repetidamente y la creación de objetos que se descartan inmediatamente lo ralentiza.

Debe rediseñar para que, en lugar de notificar a SwiftUI cuando cambie el valor predeterminado con @AppStorage , deba escuchar los valores predeterminados usted mismo, actualizar el formateador de números con los nuevos valores y decirle a SwiftUI que vuelva a dibujar.

Una forma sería hacer que numberFormatter @Published . Luego use Combine para escuchar los cambios en los dos valores predeterminados de usuario que le interesan, cree un nuevo formateador usando los valores, luego asigne el final de la canalización a la propiedad publicada numberFormatter que notificará a SwiftUI. Esto es realmente para lo que está diseñado el ObservableObject de Combine. Puede optimizar esto aún más al no tenerlo @Published y en su lugar solo un let y luego enviar manualmente el objectWillChange() y luego actualizar el formateador let para usar los nuevos parámetros de los valores predeterminados.

over 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error