I'm trying to get a numeric field updated so I'm using a TextField with the formatter: parameter set. It formats the number into the entry field just fine, but does not update the bound value when edited. The TextField works fine (on Strings) without the formatter specified. Is this a bug or am I missing something?
UPDATE: As of Xcode 11 beta 3 it kind of works. Now if you edit the numeric TextField, the bound value is updated after you hit return. The String TextField is still updated after each keypress. I guess they don't want to send the value to be formatted to the formatter with every key press, or maybe there is/will be a modifier for TextField to tell it to do that.
Note that The API has changed slightly; the old TextField init()s are deprecated and a new titleKey String field has been added as the first parameter which appears as placeholder text in the field.
struct TestView : View { @State var someText = "Change me!" @State var someNumber = 123.0 var body: some View { Form { // Xcode 11 beta 2 // TextField($someText) // TextField($someNumber, formatter: NumberFormatter()) // Xcode 11 beta 3 TextField("Text", text: $someText) TextField("Number", value: $someNumber, formatter: NumberFormatter()) Spacer() // if you change the first TextField value, the change shows up here // if you change the second (the number), // it does not *until you hit return* Text("text: \(self.someText), number: \(self.someNumber)") // the button does the same, but logs to the console Button(action: { print("text: \(self.someText), number: \(self.someNumber)")}) { Text("Log Values") } } } }
If you type in the first (String) TextField, the value in the Text view is updated immediately. If you edit the second (Numeric), nothing happens. Similarly tapping the Button shows an updated value for the String, but not the number. I've only tried this in the simulator.
You can use Binding to convert Double<-->String for TextField
struct TestView: View { @State var someNumber = 123.0 var body: some View { let someNumberProxy = Binding<String>( get: { String(format: "%.02f", Double(self.someNumber)) }, set: { if let value = NumberFormatter().number(from: $0) { self.someNumber = value.doubleValue } } ) return VStack { TextField("Number", text: someNumberProxy) Text("number: \(someNumber)") } } }
You can use computed property way to solve this issue. (thanks @ iComputerfreak)
struct TestView: View { @State var someNumber = 123.0 var someNumberProxy: Binding<String> { Binding<String>( get: { String(format: "%.02f", Double(self.someNumber)) }, set: { if let value = NumberFormatter().number(from: $0) { self.someNumber = value.doubleValue } } ) } var body: some View { VStack { TextField("Number", text: someNumberProxy) Text("number: \(someNumber)") } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With