Bad_Developer
Bad_Developer

Reputation: 537

UITextField add 3 zero at last of input number block the typing

I created an UITextField which allows users to input the only number, then auto adds 3 zeros at the last of the number string (with dot separator but now it's only showing as a comma instead of dot). For example if I input 3 the string in the text field will be 3.000 and limit at 12 characters input.

But now I have a problem is I can only input one number at the time and when I input another number it replace the old number I inputted. For example, I typed 3 in the text field it becomes 3.000, then type 2 it becomes 2.000 instead of 32.000. Below is my code to handle the typing:

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    self.textField?.text = textField.text

    let strTextOld = textField.text ?? ""
    let numStringOld = strTextOld.replacingOccurrences(of: ".", with: "", options: String.CompareOptions.literal, range: nil)
    var newValue: String = ""

    if let digit = Int(string) {
        let doubleItem = Int(numStringOld) ?? 0
        let itemNew = ((doubleItem/1000) * 10) + (Int(string) ?? 0)

        newValue = "\(itemNew * 1000)"
    }

    if string == "" {
        let doubleItem = Int(numStringOld) ?? 0
        let itemNew = Int((doubleItem / 1000) / 10)

        newValue = "\(itemNew * 1000)"
    }

    guard let text: String = textField.text else {return true}

    if newValue.length <= 12 {
        return self.formatPrice(textFormat: newValue, labelFormat: textField)
    }

    return true
}

//format price for textfield
func formatPrice(textFormat: String, labelFormat: UITextField) -> Bool {

    let formatStyle = NumberFormatter()
    formatStyle.numberStyle = .decimal

    let number = Double(textFormat.replaceMatches(regexp: "[^0-9]", with: ""))

    if let number:NSNumber = NSNumber(value: number ?? 0) {
        var strValue:String = formatStyle.string(from: number) ?? ""
        formatStyle.decimalSeparator = "."
        _ = strValue.replacingOccurrences(of: ",", with: ".")

        if number == 0 {
            strValue = ""
        }

        if labelFormat === self.textField {

            self.textField?.text = "\(strValue)"

        }

        return true
    }

    return true
}

Upvotes: 0

Views: 642

Answers (1)

Alex.Pinhasov
Alex.Pinhasov

Reputation: 166

I Added documentation for you to understand each step:

     let formatter: NumberFormatter = {
       let formatter = NumberFormatter()
       formatter.locale = Locale.current
       formatter.currencySymbol = ""
       formatter.numberStyle = .currency
       formatter.maximumFractionDigits = 0
       return formatter
     }()

     func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let suffix = ".000"
        // using NSString will allow us to replase replacing characters in range and get the newString
        guard let nsString = textField.text?.replacingOccurrences(of: suffix, with: "") as NSString? else { return false }
        // The newString that will be achieved after this function returns
        var newString = nsString.replacingCharacters(in: NSRange(location: (range.location - suffix.count) < 0 ? 0 : range.location - suffix.count, length: range.length > nsString.length ? nsString.length : range.length), with: string)

        // Going to delete a character.
        if string.isEmpty {
            // The reason we have an extra "0" is because after we return "true" the last digit will be deleted.
            textField.text = !newString.isEmpty ? "\(addCommas(to: newString.replacingOccurrences(of: ",", with: "")))\(suffix)0" : " "
            return true
        } else if newString.count <= 15 { // Going to add a character.
            newString = "\(addCommas(to: newString.replacingOccurrences(of: ",", with: "")))\(suffix)"
            textField.text = newString
        }
        return false
     }

    func addCommas(to string: String) -> String {
       guard let newNumber = Float(string) else { return string }
       return formatter.string(from: NSNumber(value: newNumber)) ?? string
    }

Upvotes: 2

Related Questions