SwiftUI TextField with formatter not working?

Solution 1:

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)")
        }
      }
}

Solution 2:

It seems while using value: as an input, SwiftUI does not reload the view for any key that users tap on. And, as you mentioned, it reloads the view when users exit the field or commit it.

On the other hand, SwiftUI reloads the view (immediately) using text: as an input whenever a key is pressed. Nothing else comes to my mind.

in my case, I did it for someNumber2 as below:

struct ContentView: View {

@State var someNumber = 123.0
@State var someNumber2 = "123"


var formattedNumber : NSNumber {

    let formatter = NumberFormatter()

    guard let number = formatter.number(from: someNumber2) else {
        print("not valid to be converted")
        return 0
    }

    return number
}

var body: some View {

    VStack {

        TextField("Number", value: $someNumber, formatter: NumberFormatter())
        TextField("Number2", text: $someNumber2)

        Text("number: \(self.someNumber)")
        Text("number: \(self.formattedNumber)")
    }
  }
}