I am using Xcode 14 Swift 5 and I am new to it. I am trying to make the textField accpet maximum 3 digits but also can have a decimal number in it with 2 digits. (E.g. the user can enter 123 or 123.45 but not 12345 nor 12134.54)
Thanks in advance.
here is my code to restrict the textField to accept max 3 digits but I can't write the rest.
// TextField Config
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
let text_Length = text.count string.count - range.length
if text_Length > 3 {
return false
}
return true
}
// Done
CodePudding user response:
To make your text field accept a maximum of three digits with a decimal number of two digits, you can use the NSCharacterSet class to define the characters that are allowed in the text field. You can then use the rangeOfCharacter method to check if the entered text contains any characters that are not in the allowed set.
Here is an example of how you can implement this in your code:
let allowedCharacters = CharacterSet(charactersIn: "0123456789.")
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
if let _ = string.rangeOfCharacter(from: allowedCharacters.inverted) {
return false
}
let text_Length = text.count string.count - range.length
if text_Length > 3 {
return false
}
return true
}
You can further improve this code by checking if the entered text contains a decimal point and, if so, limiting the number of digits after the decimal point to two. You can also use regular expressions to validate the entered text, which can make the code more concise and readable.
CodePudding user response:
Regular expressions are often the quick-and-dirty to solution for this sort of stuff:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let original = textField.text ?? ""
guard let range = Range(range, in: original) else { return true }
let result = original.replacingCharacters(in: range, with: string)
let match = result.range(of: #"^\s*[0-9]{0,3}(\.[0-9]{0,2})?\s*$"#, options: .regularExpression)
// in Swift 5.7, you might use Regex
//
// let match = result.wholeMatch(of: /\s*[0-9]{0,3}(\.[0-9]{0,2})?\s*/)
return match != nil
}
The regex is matching zero to three digits, optionally follows by a period and an additional zero to two digits, and ignores whitespace.
Note, this will permit the entry of a value of “.5”, for example, without the leading zero. So, when converting to a numeric value, you might want to either add the leading zero (either during entry or when converting to a numeric value) or have the regex require at least one digit before the .
:
let match = result.wholeMatch(of: /\s*[0-9]{0,2}([0-9]\.[0-9]{0,2})?\s*/)
Personally, I think it is better to let the user enter .5
and clean it up at the end, adding a leading 0
to make it 0.5
, when parsing the text field input. But, you can do whatever you like.