1
votes

I'm trying to implement a TextField with a number input together with Stepper to control quantity. After entering a number in the TextField the Stepper loses the ability to change the number. I'm pretty sure there is a trick with Binding value, but can't figure out what exactly.

struct TestView: View {
  @State var quantity: Int = 0

  var body: some View {
    HStack {
      TextField("", value: $quantity, formatter: NumberFormatter())
      Stepper("", onIncrement: {
        self.quantity += 1
      }, onDecrement: {
        self.quantity -= 1
      })
    }
  }
}
1

1 Answers

2
votes

This is because using NumberFormatter in TextField is bugged.

You may need to use a custom binding instead:

struct ContentView: View {
    @State var quantity: Int = 0

    static let formatter = NumberFormatter()

    var binding: Binding<String> {
        .init(get: {
            "\(self.quantity)"
        }, set: {
            self.quantity = Int($0) ?? self.quantity
        })
    }

    var body: some View {
        HStack {
            TextField("", text: binding)
            Stepper("", onIncrement: {
                self.quantity += 1
            }, onDecrement: {
                self.quantity -= 1
            })
        }
    }
}

Also don't recreate NumberFormatter every time:

TextField("", value: $quantity, formatter: NumberFormatter())

You can use a static property which is only created once:

static let formatter = NumberFormatter()