May Phyu
May Phyu

Reputation: 905

UITextfield character count limits in Swift

In text field, I only want to allow 16 characters. I don't want to allow to type over 16 characters. Here is my codes;

let currentCharacterCount = txtPinNo.text?.characters.count ?? 0
    if (range.length + range.location > currentCharacterCount){
        return false
    }
    let newLength = currentCharacterCount + string.characters.count - range.length
    return newLength <= 19

My Expected Result is --> 1234-1111-3333-6666 (19 characters)
My Actual Outcome Result is --> 1234-1111-2222-4444-4 (the last number always appear, just want to remove "-4")

I don't want to allow to type when over 16 characters. Please help me how to check it.

Upvotes: 0

Views: 475

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236340

You can subclass UITextField and create a custom field as follow:

@IBDesignable
class LimitedLengthField: UITextField {
    @IBInspectable var maxLength: Int = 16 // set maximum number of characters
    var stringValue: String { return text ?? "" }
    override func awakeFromNib() {
        super.awakeFromNib()
        keyboardType = .ASCIICapable   // set the keyboard type
        addTarget(self, action: #selector(editingChanged), forControlEvents: .EditingChanged)
        editingChanged(self)
    }
    func editingChanged(sender: UITextField) {
        sender.text = String(stringValue.characters.prefix(maxLength))
    }
}

If you need to ad some custom formatting it would get a little but trickier:

Swift 2

class CustomField: UITextField {
    var stringValue: String { return text ?? "" }
    var decimalDigits: String {
        return stringValue
            .componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)
            .joinWithSeparator("") ?? ""
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        addTarget(self, action: #selector(editindChanged(_:)), forControlEvents: .EditingChanged)
        keyboardType = .NumberPad
        editindChanged(self)
    }
    func editindChanged(sender: UITextField) {
        let letters = Array(decimalDigits.stringByPaddingToLength(16, withString: " ", startingAtIndex: 0).characters)
        switch decimalDigits.characters.count {
        case 1...4:
            text = decimalDigits
        case 5...8:
            text = (String(letters[0...3]) + "-"
                + String(letters[4...7]))
                .stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
        case 9...12:
            text = (String(letters[ 0...3 ]) + "-"
                + String(letters[ 4...7 ]) + "-"
                + String(letters[8...11]))
                .stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
        case 13...16:
            text = (String(letters[ 0...3 ]) + "-"
                + String(letters[ 4...7 ]) + "-"
                + String(letters[8...11]) + "-"
                + String(letters[12...15]))
                .stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
        default:
            print(text)
            if decimalDigits.characters.count > 0 {
                text = String(text!.characters.prefix(19))
            }
        }
    }
}

Swift 3

class CustomField: UITextField {
    var stringValue: String { return text ?? "" }
    var decimalDigits: String {
        return stringValue
            .components(separatedBy: CharacterSet.decimalDigits.inverted)
            .joined(separator: "") ?? ""
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        addTarget(self, action: #selector(editindChanged(_:)), for: .editingChanged)
        keyboardType = .numberPad
        editindChanged(self)
    }
    func editindChanged(_ sender: UITextField) {
        let letters = Array(decimalDigits.padding(toLength: 16, withPad: " ", startingAt: 0).characters)
        switch decimalDigits.characters.count {
        case 1...4:
            text = decimalDigits
        case 5...8:
            text = (String(letters[0...3]) + "-"
                  + String(letters[4...7]))
                  .trimmingCharacters(in: .whitespaces)
        case 9...12:
            text = (String(letters[ 0...3 ]) + "-"
                  + String(letters[ 4...7 ]) + "-"
                  + String(letters[8...11]))
                  .trimmingCharacters(in:. whitespaces)
        case 13...16:
            text = (String(letters[ 0...3 ]) + "-"
                + String(letters[ 4...7 ]) + "-"
                + String(letters[8...11]) + "-"
                + String(letters[12...15]))
                .trimmingCharacters(in: .whitespaces)
        default:
            print(text)
            if decimalDigits.characters.count > 0 {
                text = String(text!.characters.prefix(19))
            }
        }
    }
}

Upvotes: 1

Related Questions