I am looking for a textfield currency formatter such that it fulfils the following criterias:
- It should be formatted(comma separated) as I am typing
 - 10 digits before decimal point and 2 digits after it, should be allowed
 - It should allow a regex for (2)
 - When we cut, cursor should remain at the same place
 - When we type in the middle of the currency, cursor should not shift to left.
 - It should support localization (Commas and Periods) in regex.
 
I have tried alot of solutions:
Using
NSCharacterSet(This is the closest but regex fails here due to interchange of.and,during localization, also we have used.decimaltype here to avoid the$in textField)class func checkTextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard let textBeforeEditing = textField.text else { return true } if ((string == "0" || string == "") && (textField.text! as NSString).range(of: ".").location < range.location) { return true } var currentPosition = 0 if let selectedRange = textField.selectedTextRange { currentPosition = textField.offset(from: textField.beginningOfDocument, to: string == "" ? selectedRange.end : selectedRange.start) } let allowedCharacterSet = NSCharacterSet(charactersIn: "0123456789.").inverted let filtered = string.components(separatedBy: allowedCharacterSet) let component = filtered.joined(separator: "") let isNumeric = string.replacingOccurrences(of: ",", with: "") == component var textFieldString : String = "" var numberWithoutCommas : String = "" guard isNumeric else { return false } let formatter = NumberFormatter() formatter.numberStyle = .decimal textFieldString = (textField.text! as NSString).replacingCharacters(in: range, with: string) numberWithoutCommas = textFieldString.replacingOccurrences(of: ",", with: "") let formattedNumberWithoutCommas = formatter.number(from: numberWithoutCommas) guard let formattedNumber = formattedNumberWithoutCommas, var formattedString = formatter.string(from: formattedNumber) else { textField.text = nil return false } if string == "." && range.location == textField.text?.count { formattedString = formattedString.appending(".") } textField.text = formattedString currentPosition = getCursorPositionForTextField(string: string, cursorPosition: currentPosition, formattedString: formattedString, textBeforeEditing: textBeforeEditing) handleTextFieldCursor(cursorPosition: currentPosition, textField: textField) return false }Using
NumberFormatterbut cursor shifts to end on every cut/pasteextension String { func currencyInputFormatting() -> String { var number: NSNumber! let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.maximumFractionDigits = 2 formatter.minimumFractionDigits = 2 var amountWithPrefix = self // remove from String: "$", ".", "," let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive) amountWithPrefix = regex.stringByReplacingMatches(in: amountWithPrefix, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count), withTemplate: "") let double = (amountWithPrefix as NSString).doubleValue number = NSNumber(value: (double / 100)) guard number != 0 as NSNumber else { return "" } return formatter.string(from: number)! } }
I have spent almost a day or two finding a 100% workable solution but not able to resolve. Any help will be appreciated
EDIT
I have come quite close to the solution with the help of the @denis_lor answer but still unable to achieve the interchange of comma with period. Here's my updated code, am I missing something? It works fine with english but not with spanish.
class func checkTextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let textBeforeEditing = textField.text else {
        return true
    }
    if ((string == "0" || string == "") && (textField.text! as NSString).range(of: "\(NSLocalizedString("core_decimal_separator_symbol", comment: ""))").location < range.location) {
        return true
    }
    var currentPosition = 0
    if let selectedRange = textField.selectedTextRange {
        currentPosition = textField.offset(from: textField.beginningOfDocument, to: string == "" ? selectedRange.end : selectedRange.start)
    }
    let allowedCharacterSet = NSCharacterSet(charactersIn: "0123456789\(NSLocalizedString("core_decimal_separator_symbol", comment: ""))").inverted
    let filtered = string.components(separatedBy: allowedCharacterSet)
    let component = filtered.joined(separator: "")
    let isNumeric = string.replacingOccurrences(of: NSLocalizedString("core_thousand_separator_symbol", comment: ""), with: "") == component
    var textFieldString : String = ""
    var numberWithoutCommas : String = ""
    guard isNumeric else {
        return false
    }
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    textFieldString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
    numberWithoutCommas = textFieldString.replacingOccurrences(of: NSLocalizedString("core_thousand_separator_symbol", comment: ""), with: "")
    let formattedNumberWithoutCommas = formatter.number(from: numberWithoutCommas)
    guard let formattedNumber = formattedNumberWithoutCommas, var formattedString = formatter.string(from: formattedNumber) else {
        textField.text = nil
        return false
    }
    if string == NSLocalizedString("core_decimal_separator_symbol", comment: "") && range.location == textField.text?.count {
        formattedString = formattedString.appending(NSLocalizedString("core_decimal_separator_symbol", comment: ""))
    }
    textField.text = formattedString
    currentPosition = getCursorPositionForTextField(string: string, cursorPosition: currentPosition, formattedString: formattedString, textBeforeEditing: textBeforeEditing)
    handleTextFieldCursor(cursorPosition: currentPosition, textField: textField)
    return false
}

