How to limit the number of characters in a UITextField?
I need to to display max 10 characters
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let textFieldCadena = textField.text, let range = Range(range, in: textFieldCadena) else {
return false
}
let nuevaCadena = textFieldCadena.replacingCharacters(in: range, with: string)
if nuevaCadena.isEmpty {
textField.text = "0"
return false
} else if textField.text == "0" {
textField.text = string
return false
}
if textField == textField {
let allowedCharacters = CharacterSet(charactersIn:"0123456789 ")
let characterSet = CharacterSet(charactersIn: string)
return allowedCharacters.isSuperset(of: characterSet)
}
return true
}
As decribed here You can use .maxlength in swift 5 to set character length. Credit to article here:
https://www.swiftdevcenter.com/max-character-limit-of-uitextfield-and-allowed-characters-swift/
self.textField.maxLength = 10
Do the check for character count first
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard
let textFieldCadena = textField.text,
let range = Range(range, in: textFieldCadena),
textFieldCadena.count <= 10
else { return false }
...
}
Related
I need to specify a maximum value for a text field. I already got an answer from another post on how to restrict a UITextField to numbers only. But I would like to modify that function to only accept a number between 0 and 540.
Is there any way to modify that function?
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let s = NSString(string: textField.text ?? "").replacingCharacters(in: range, with: string)
guard !s.isEmpty else { return true }
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .none
return numberFormatter.number(from: s)?.intValue != nil
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
print(string)
let myRange = 0...540
//ro delete/remove values in textField
if string == "" {
return true
}
let fullText = NSString(string: textField.text ?? "").replacingCharacters(in: range, with: string)
if let wholeNumber = Int(fullText), myRange.contains(wholeNumber) {
return true
}
return false
}
You can check if number lies between 0 and 540.
if let number = numberFormatter.number(from: s)?.intValue {
return number > 0 && number < 540
} else {
return true
}
Is there a way to limit a UITextField to only numeric value as well as limiting the length.
I have the below two functions but don't know how I can use the shouldChangeCharactersIn twice in the same delegate. Any ideas how to use both of these
// Allow Numeric Only in Quantity
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let allowCharacters = ".-+1234567890"
let allowedCharacterSet = CharacterSet(charactersIn: allowCharacters)
let typedCharacterSet = CharacterSet(charactersIn: string)
return allowedCharacterSet.isSuperset(of: typedCharacterSet)
}
// Limit the length of the input
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
return count <= 20
}
Many Thanks
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"
}
How can i add another condition to my function, for another textfield and how to make this code is more simple
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text {
if let floatingLabelTextField = textField as? SkyFloatingLabelTextField {
if(text.characters.count < 3 || !text.containsString("#")) {
floatingLabelTextField.errorMessage = "Invalid email"
}
else {
// The error message will only disappear when we reset it to nil or empty string
floatingLabelTextField.errorMessage = ""
}
}
}
return true
}
Below code will be more simpler and easy to add any new condition:
func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailTest.evaluate(with: testStr)
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else{
return true
}
guard let floatingLabelTextField = textField as? SkyFloatingLabelTextField else {
return true
}
if isValidEmail(testStr: text) {
floatingLabelTextField.errorMessage = ""
}else{
floatingLabelTextField.errorMessage = "Invalid email"
}
return true
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
if textField == textField as? SkyFloatingLabelTextField && (!textField.text.containsString("#") || textField.text.characters.count < 3 )
{
floatingLabelTextField.errorMessage = "Invalid email"
}
else
{
floatingLabelTextField.errorMessage = ""
}
return true
}
You can check firstly if textfield is your selected textfield and in same condition you can also check email validation.
I would like to put a limit for textfield. Example: Max character count should be 6 and characters can be digits only. But i could not put these two controls in one function.
First func for count of the text:
func textFieldCharacterCountLimit(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let maxLength = 6
let currentString: NSString = txt_phone_no_verification_code.text! as NSString
let newString: NSString =
currentString.replacingCharacters(in: range, with: string) as NSString
return newString.length <= maxLength
}
Second func for type of the text:
func textFieldCharacterTypeLimit(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let allowedCharacters = CharacterSet.decimalDigits
let characterSet = CharacterSet(charactersIn: string)
return allowedCharacters.isSuperset(of: characterSet)
}
Beside this, it gives an error also. And textFieldCharacterCountLimit function does not work. I think i get an error because two functions effect same textfield with return. Thanks
Allowing only a specified set of characters to be entered into a given text field with specific range
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.count == 0 {
return true
}
let currentText = textField.text ?? ""
let prospectiveText = (currentText as NSString).replacingCharacters(in: range, with: string)
return prospectiveText.containsOnlyCharactersIn(matchCharacters: "0123456789") &&
prospectiveText.count <= 6
}
String extension with condition
extension String {
// Returns true if the string contains only characters found in matchCharacters.
func containsOnlyCharactersIn(matchCharacters: String) -> Bool {
let disallowedCharacterSet = NSCharacterSet(charactersIn: matchCharacters).inverted
return self.rangeOfCharacter(from: disallowedCharacterSet as CharacterSet) == nil
}
}
How to program an iOS text field that takes only numeric input with a maximum length
http://www.globalnerdy.com/2015/04/27/how-to-program-an-ios-text-field-that-takes-only-numeric-input-or-specific-characters-with-a-maximum-length/
You can't just make up delegate method names. You need to implement the proper method and do all of your needed checking in the one method.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
if newString.count > 6 {
return false
}
return newString.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
}
In my app, I have 2 text fields. taskTextField and DescTextField. I would like to limit the characters of the task text field to 15 and the description text field to 20. I have managed to limit both but I don't know how to do them separately. Here is my code for both:
let limitLength = 20
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= limitLength
}
Any help on how to make separate limits for each text field would be appreciated.
Add a tag for each UITextField:
let taskTextFieldTag = 100
let DescTextFieldTag = 101
override func viewDidLoad() {
// ..
taskTextField.tag = taskTextFieldTag
DescTextField.tag = DescTextFieldTag
// ...
}
In the UITextFieldDelegate:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else {
return false
}
let newLength = text.utf16.count + string.utf16.count - range.length
var maxLength = 0
switch textField.tag {
case taskTextFieldTag:
maxLength = 15
case DescTextFieldTag:
maxLength = 20
default: break
}
return newLength <= maxLength
}
Based on your code assuming you can connect the text fields to your code via IBOutlets
#IBOutlet weak var taskTextField: UITextField!
#IBOutlet weak var descTextField: UITextField!
let taskTextFieldlimitLength = 15
let descTextFieldlimitLength = 20
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
switch textField {
case taskTextField:
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= taskTextFieldlimitLength
case descTextField:
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= descTextFieldlimitLength
default:
return true
}
}