You can do it like this
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let textFieldText = textField.text,
let rangeOfTextToReplace = Range(range, in: textFieldText) else {
return false
}
let substringToReplace = textFieldText[rangeOfTextToReplace]
let count = textFieldText.count - substringToReplace.count + string.count
let allowedCharacters = ".-+1234567890"
let allowedCharcterSet = CharacterSet(charactersIn: allowedCharacters)
let typedCharcterSet = CharacterSet(charactersIn: string)
if allowedCharcterSet.isSuperset(of: typedCharcterSet)
, count <= 20 {
return true
} else {
return false
}
}
Or you can use this Subclass of UITextField
class JDTextField: UITextField {
@IBInspectable var maxLength: Int = 0 // Max character length
var valueType: ValueType = ValueType.none // Allowed characters
/************* Added new feature ***********************/
// Accept only given character in string, this is case sensitive
@IBInspectable var allowedCharInString: String = ""
func verifyFields(shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
switch valueType {
case .none:
break // Do nothing
case .onlyLetters:
let characterSet = CharacterSet.letters
if string.rangeOfCharacter(from: characterSet.inverted) != nil {
return false
}
case .onlyNumbers:
let numberSet = CharacterSet.decimalDigits
if string.rangeOfCharacter(from: numberSet.inverted) != nil {
return false
}
case .phoneNumber:
let phoneNumberSet = CharacterSet(charactersIn: "+0123456789")
if string.rangeOfCharacter(from: phoneNumberSet.inverted) != nil {
return false
}
case .alphaNumeric:
let alphaNumericSet = CharacterSet.alphanumerics
if string.rangeOfCharacter(from: alphaNumericSet.inverted) != nil {
return false
}
case .fullName:
var characterSet = CharacterSet.letters
print(characterSet)
characterSet = characterSet.union(CharacterSet(charactersIn: " "))
if string.rangeOfCharacter(from: characterSet.inverted) != nil {
return false
}
}
if let text = self.text, let textRange = Range(range, in: text) {
let finalText = text.replacingCharacters(in: textRange, with: string)
if maxLength > 0, maxLength < finalText.utf8.count {
return false
}
}
// Check supported custom characters
if !self.allowedCharInString.isEmpty {
let customSet = CharacterSet(charactersIn: self.allowedCharInString)
if string.rangeOfCharacter(from: customSet.inverted) != nil {
return false
}
}
return true
}
}
How to use it
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Verify all the conditions
if let sdcTextField = textField as? JDTextField {
return sdcTextField.verifyFields(shouldChangeCharactersIn: range, replacementString: string)
} else {
return true
}
}
And in viewDidLoad()
you set characteristics in just one line
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.textField.delegate = self
self.textField.maxLength = 10
self.textField.allowedCharInString = ".-+1234567890"
}