Search code examples
swiftuiios17

TextField(SwiftUI) focusing state setter is not working properly - iOS 17


In iOS 17.0, Inline setter value of focused TextField in SwiftUI is not reflecting on the TextFieldUI properly, unless that TextField is focused out.

Issue is occuring in both simulator and physical device loaded with iOS 17.

struct ContentView: View{
    @State var cardNumber: String = ""
    var body: some View{
            TextField("", text: .init(get: {
                cardNumber
            }, set: { value in
                cardNumber = ""
                let startIndex = value.startIndex
                for index in 0..<value.count{
                    let stringIndex = value.index(startIndex, offsetBy: index)
                    cardNumber += String(value[stringIndex])
                    if (index + 1) % 5 == 0 && value[stringIndex] != " "{
                        cardNumber.insert(" ", at: stringIndex)
                    }
                }
                cardNumber = String(cardNumber.prefix(23))  
            })).background(Color.yellow) 
    } 
}

It used to work in iOS 15 and in iOS 16. enter image description here


Solution

  • From iOS 17, inline getter and setter of the binded variable seems to be not working. But the onChange event of the TextField seems to be updating the UI dynamically.

            if #available(iOS 17.0, *) {
            TextField("", text: $cardNumber).onChange(of: cardNumber, initial: focusedField == .amount, { oldValue, newValue in
                if oldValue != newValue{
                    if newValue.count == 4 && oldValue.count == 3{
                        cardNumber = newValue + " "
                    } else if oldValue.count == 8 && newValue.count == 9{
                        cardNumber = newValue + " "
                    } else if oldValue.count == 13 && newValue.count == 14{
                        cardNumber = newValue + " "
                    } else if oldValue.count == 18 && newValue.count == 19{
                        cardNumber = newValue + " "
                    } else if oldValue.count == 23{
                        cardNumber = oldValue
                    }
                }
                return
            })
               
        }