Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Textfiled Binding triggering 2 times in iOS 15

Tags:

ios

swift

swiftui

I have a OTP screen where user enters his OTP (6-digits) on a text filed (hidden on background) and once user enters the 6th digit, I will dismiss my keyboard and make an API call.

 private var maxDigits: Int = 6
 @Binding private var pin: String

private var backgroundField: some View {
        
   let boundPin = Binding<String>(get: { self.pin }, set: { newValue in
      self.pin = newValue
      self.submitPin() // API call method
   })
        
   return TextField("", text: boundPin, onCommit: submitPin)
           .accentColor(.clear)
           .foregroundColor(.clear)
           .keyboardType(.numberPad)
           .introspectTextField { textField in
                    textField.tintColor = .clear
                    textField.textColor = .clear
                    textField.keyboardType = .numberPad
                    textField.textContentType = .oneTimeCode
                    if pin.count == maxDigits {
                        textField.resignFirstResponder()
                    } else {
                        textField.becomeFirstResponder()
                    }
                }
    }

The problem I am running into on iOS 15 is, when user enters the 6th digit, the "submitPin" method is getting called 2 times. This is happening only on iOS 15 not on prior OS versions like iOS 14/13/12.

Is this an open bug with Apple (or) what should I need to do to fix this.

Reference Article - https://medium.com/flawless-app-stories/swiftui-passcode-field-for-otp-and-pin-entry-b61ba663dc31

like image 737
Venkata Avatar asked Jan 26 '26 20:01

Venkata


1 Answers

you could try something like this, works for me on ios 15:

 struct ContentView: View {
    private var maxDigits: Int = 6
    @State private var pin: String = ""
    
    private var backgroundField: some View {
        TextField("enter 6 digits pin number", text: Binding(
            get: { pin },
            set: { newValue in
                if newValue.count == maxDigits {
                    pin = newValue
                    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                    submitPin()
                }
            }))
            .accentColor(.clear)  
            .foregroundColor(.clear)
            .keyboardType(.numberPad)
    }
    
    var body: some View {
        backgroundField.border(.red).padding()
    }

    func submitPin() {
        print("----> submitPin pin: \(pin) ")
    }
}
like image 55
workingdog support Ukraine Avatar answered Jan 29 '26 08:01

workingdog support Ukraine



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!