Home > Software engineering >  How to limit number of decimals in textfield when user input is from pasteboard, iOS Swift
How to limit number of decimals in textfield when user input is from pasteboard, iOS Swift

Time:11-18

I have a textfield where user can input only 6 decimals, if there are decimals, if there aren't then he is allowed to input as many characters as user wants.

For example, I am allowing this: 7472828282 and this: 0,123456, not this: 0,2139213773219312.

And my current implementation is ok with this examples above and when user is making input from ekeyboard, but I can't manage to make it work when user pastes some value, for example user can paste this value: 0,123456789, but I would like to cut it after 6th decimal, to be actually like this: 0,123456, and no, I don't need to round it on bigger decimal, I need to cut it!

Thanks for help, my so far code is below

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField === self.amountView.textField {
    
    guard let text = textField.text, let decimalSeparator = NSLocale.current.decimalSeparator else {
        return true
    }
    
    var splitText = text.components(separatedBy: decimalSeparator)
    let totalDecimalSeparators = splitText.count - 1
    let isEditingEnd = (text.count - 3) < range.lowerBound
    
    splitText.removeFirst()
    
    if  splitText.last?.count ?? 0 > 5 && string.count != 0 && isEditingEnd {
        return false
    }
    
    if totalDecimalSeparators > 0 && string == decimalSeparator {
        return false
    }
}
return true
}

CodePudding user response:

This code always updates the content of textField but limits the number of decimals:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    guard let decimalSeparator = NSLocale.current.decimalSeparator else {return true}

    // Updates the text
    var updatedText = (textView.text as NSString).replacingCharacters(in: range, with: text) 

    // If someone needs to cover all possible decimal separator values, the commented line below is the solution
    // let textComponents = updatedText.components(separatedBy: [",", "."])

    let textComponents = updatedText.components(separatedBy: decimalSeparator)
    
    // Truncates the decimals
    if textComponents.count > 1 && textComponents[1].count > 6{
       updatedText = textComponents[0].appending(decimalSeparator).appending((textComponents[1] as NSString).substring(to: 6))
    }
        
    textView.text = updatedText

    // The text has already been updated, so returns false
    return false 
}

CodePudding user response:

Your mistake: You are checking the old content.

shouldChangeCharacters gives you the old text (still in the text field), a range to be replaced (selection or just insertion point) and replacement. You first need to calculate the new text if the range was replaced, and then check that result.

  • Related