Reputation:
How to limit the lenght of several UItextField in this way:
Max integer allowed two and max decimal allowed one.
I've used this code to limit the text to two number:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var kMaxLength = 2
let oldString = textFieldlOne.text as NSString
let string = oldString.stringByReplacingCharactersInRange(range, withString: string)
return countElements(string) <= kMaxLength
}
But I have several UITextfield IBOutlet and I want allow the user to insert one decimal number es. 12.5
Upvotes: 1
Views: 3928
Reputation: 764
In swift 3, limit textfield's input value before and after decimal
let digitBeforeDecimal = 2
let digitAfterDecimal = 2
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let computationString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
let arrayOfSubStrings = computationString.components(separatedBy: ".")
if arrayOfSubStrings.count == 1 && computationString.count > digitBeforeDecimal {//
return false
} else if arrayOfSubStrings.count == 2 {
let stringPostDecimal = arrayOfSubStrings[1]
return stringPostDecimal.count <= digitAfterDecimal
}
return true
}
Upvotes: 0
Reputation: 4946
Swift 4
Using number formatter
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let s = (textField.text ?? "").appending(string)
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
return numberFormatter.number(from: s)?.doubleValue != nil
}
Upvotes: 0
Reputation: 437422
Regular expressions are useful when trying to test to see if a string matches a particular template:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let oldString = textField.text ?? "" as NSString
let candidate = oldString.stringByReplacingCharactersInRange(range, withString: string)
let regex = try? NSRegularExpression(pattern: "^\\d{0,2}(\\.\\d?)?$", options: [])
return regex?.firstMatchInString(candidate, options: [], range: NSRange(location: 0, length: candidate.characters.count)) != nil
}
The \d{0,2}
matches zero to two digits. The (\.\d?)?
translates to "if there is a decimal point, allow it and optionally one more digit." (You could also do (\.\d{0,1})?
, too.) The ^
matches the "start of the string" and the $
matches the "end of the string" (i.e., we'll only find matches where the \d{0,2}(\.\d?)?
is the entire string, and not just something that shows up in the middle of the string.) And, of course, all of those \
characters are escaped to be \\
in the string literal.
Regular expressions (regex) can be a little "dense" when you first encounter them, but once you gain familiarity with the syntax, it's an incredibly powerful tool.
--
By the way, I notice that you said in a comment that you're using Swift 1.1. I believe the equivalent Swift 1.1 syntax would be something like:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let oldString = textField.text as NSString
let candidate = oldString.stringByReplacingCharactersInRange(range, withString: string)
var error: NSError?
let regex = NSRegularExpression(pattern: "^\\d{0,2}(\\.\\d?)?$", options: 0, error: &error)
return regex?.firstMatchInString(candidate, options: 0, range: NSRange(location: 0, length: candidate.length)) != nil
}
I don't have a Swift 1.1 compiler readily available, so I can't easily test/confirm this Swift 1.1 syntax, but if I recall correctly, it's something like that. Personally I'd recommend upgrading to the latest version of Xcode, but to each his own.
Upvotes: 5
Reputation: 14030
here is a swift conversion from @Vijayts answer:
struct Constants {
static let MAX_BEFORE_DECIMAL_DIGITS = 2
static let MAX_AFTER_DECIMAL_DIGITS = 1
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let computationString = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
// Take number of digits present after the decimal point.
let arrayOfSubStrings = computationString.componentsSeparatedByString(".")
if arrayOfSubStrings.count == 1 && computationString.characters.count > Constants.MAX_BEFORE_DECIMAL_DIGITS {
return false
} else if arrayOfSubStrings.count == 2 {
let stringPostDecimal = arrayOfSubStrings[1]
return stringPostDecimal.characters.count <= Constants.MAX_AFTER_DECIMAL_DIGITS
}
return true
}
Upvotes: 1
Reputation: 2295
I am not so adept with swift at this point in time. So I will try to solve it in Obj-C first.
#define MAX_BEFORE_DECIMAL_DIGITS = 2
#define MAX_AFTER_DECIMAL_DIGITS = 1
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *computationString = [textField.text stringByReplacingCharactersInRange:range withString:string];
// Take number of digits present after the decimal point.
NSArray *arrayOfSubStrings = [newString componentsSeparatedByString:@"."];
if(([arrayOfSubStrings count] == 1) && (computationString.length > MAX_BEFORE_DECIMAL_DIGITS)) {
return NO;
} else if([arrayOfSubStrings count] == 2) {
NSString *stringPostDecimal = [NSString stringWithFormat:@"%@",[arrayOfSubStrings objectAtIndex:1]];
return !([stringPostDecimal length] > MAX_AFTER_DECIMAL_DIGITS);
}
return YES;
}
Define the value of MAX_BEFORE_DECIMAL_DIGITS and MAX_AFTER_DECIMAL_DIGITS as per your requirement.
Upvotes: 0