iosswiftswiftuitextfieldstepper

SwiftUI TextField + Stepper


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

Solution

  • 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()