1

I am using below code from another post to format UITextField for phone number in US but when the user starts typing instead of clearing the text I want the placeholder to stay. For eg. +1 (XXX) XXX-XXXX after typing should be like +1 (23X) XXX-XXXX. Rather than completely clearing the placeholder I want it to stay as a guide to user.

Code i am currently using:

    func textFieldDidBeginEditing(textField: UITextField) {
    if (textField == self.mobileNumberTextField) {
        textField.text = "+"
    }
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if (textField == self.mobileNumberTextField) {
        let newString = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)

        if (newString.characters.count < textField.text?.characters.count && newString.characters.count >= 1) {
            return true                                                         // return true for backspace to work
        } else if (newString.characters.count < 1) {
            return false;                        // deleting "+" makes no sence
        }
        if (newString.characters.count > 17 ) {
            return false;
        }

        let components = newString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)

        let decimalString = components.joinWithSeparator("") as NSString
        let length = decimalString.length

        var index = 0
        let formattedString = NSMutableString()
        formattedString.appendString("+")

        if (length >= 1) {
            let countryCode = decimalString.substringWithRange(NSMakeRange(0, 1))
            formattedString.appendString(countryCode)
            index += 1
        }

        if (length > 1) {
            var rangeLength = 3
            if (length < 4) {
                rangeLength = length - 1
            }
            let operatorCode = decimalString.substringWithRange(NSMakeRange(1, rangeLength))
            formattedString.appendFormat(" (%@) ", operatorCode)
            index += operatorCode.characters.count
        }

        if (length > 4) {
            var rangeLength = 3
            if (length < 7) {
                rangeLength = length - 4
            }
            let prefix = decimalString.substringWithRange(NSMakeRange(4, rangeLength))
            formattedString.appendFormat("%@-", prefix)
            index += prefix.characters.count
        }

        if (index < length) {
            let remainder = decimalString.substringFromIndex(index)
            formattedString.appendString(remainder)
        }

        textField.text = formattedString as String

        if (newString.characters.count == 17) {
            textField.resignFirstResponder()
        }

        return false
    }

    return true
}
Ankit Khanna
  • 1,019
  • 2
  • 12
  • 22

1 Answers1

1

I would suggest you use a default text in textfield. You can do same with placeholder, I think

Think of this default string as an array of characters. You should track each key pressed and replace the character at the index in default string with the substring that was entered (at that index in default string.) And when character is removed, you should replace back with that character (X).

Try something like:

var defaultstring = "+1 (XXX) XXX-XXXX"
var yourtextField = UITextField()

override func viewDidLoad() {
  yourtextField.text = defaultstring
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
   if string != "" {
        var range = self.defaultstring.rangeOfString("X")

        self.defaultstring.replaceRange(range!, with: string)
        self.yourtextField.text = self.defaultstring
// I tested, this is working. 
    }

    else if substring == "" {
        // THis case if when user presses backspace.. 
        let idx = self.defaultstring.characters.indexOf("X")?.advancedBy(-1)
        let range = self.defaultstring.rangeOfComposedCharacterSequenceAtIndex(idx!)
        self.defaultstring.replaceRange(range, with: "X")

    }

}

This code would work but there are some things you will need to take care about such as : End cases, where user types more characters than the allowed Replacing only "X" with typed character has been taken care of If user uses backSpace, it will work, but if the range is advanced by -1 and next char you have to replace is "-", then you should check for that and advance once more by -1, so that character to replace is for sure X

Ask questions for any details.

Akshansh Thakur
  • 5,163
  • 2
  • 21
  • 38