'Editing a SwiftUI TextField on the fly

I want to be able to edit a text field as the user types character by character. I want to be able to take a number field and as the user types:

  1. Filter out non-numeric characters and return back only the characters already entered that are valid.
  2. Format the number such that when the user enters they get the number in reverse. ie 120.36 would appear as: 0.01 0.12 1.20 12.03 120.36

If the user enters an invalid character then return the string with out the invalid character. I'm stuck on how to capture the TextField, edit it and return it formatted as I've shown.

I've gotten this far: (Not far :-) I've tried a number of solutions from here on StackOverflow but none seem to get me where I want to go.. onEditChange onChange etc.

struct SwiftUIView: View {

@State var amount: String = "0.00"
var body: some View {
    
    TextField(
        "Enter amount here ",
        text: $amount
    )

}

}



Solution 1:[1]

I ran into the same issue! Using the accepted answer as inspiration (thank you for posting!) I was able to come up with a less kludgy solution.

import SwiftUI

struct Example: View {
    
    @Binding var valueText: String
    
    var body: some View {
        TextField("Enter Value", text: $valueText)
            .onChange(of: valueText, perform: { newValue in
                valueText = editOnTheFly(input: newValue, leadingZeros: 0, decimalPlaces: 2)
            })
    }
    
    func editOnTheFly(input: String, leadingZeros: Int, decimalPlaces: Int) -> String {
        // Strip all non-numeric characters from the String
        var result = input.replacingOccurrences(of: "[^0123456789]", with: "", options: .regularExpression)
        
        // If the String can't be cast as a Double return ""
        guard let resultAsDouble = Double(result) else {
            return ""
        }
        
        let formatter = NumberFormatter()
        formatter.minimumIntegerDigits = leadingZeros
        formatter.minimumFractionDigits = decimalPlaces
        formatter.maximumFractionDigits = decimalPlaces

        // If `2` decimalPlaces past in, the divider would be 100.0
        let dividerDecimal = pow(10.0, decimalPlaces)
        let dividerDouble = NSDecimalNumber(decimal: dividerDecimal).doubleValue
        
        // Turns an input of `42` into `0.42`
        result = formatter.string(from: NSNumber(value: resultAsDouble/dividerDouble)) ?? ""
        
        return result
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 maxrgnt