I have a UITextField that when clicked brings up a number pad with a decimal point in the bottom left. I am trying to limit the field so that a user can only place 1 decimal
Implement the shouldChangeCharactersInRange method like this:
// Only allow one decimal point
// Example assumes ARC - Implement proper memory management if not using.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *arrayOfString = [newString componentsSeparatedByString:@"."];
if ([arrayOfString count] > 2 )
return NO;
return YES;
}
This creates an array of strings split by the decimal point, so if there is more than one decimal point we will have at least 3 elements in the array.
Here is an example with a regular expression, the example limits to only one decimal point and 2 decimals. You can tweak it to fit your needs.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = @"^[0-9]*((\\.|,)[0-9]{0,2})?$";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
return numberOfMatches != 0;
}
In whatever object you set your UITextField's delegate to, add a method that answers to "[- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string]".
Then you can either use a NSNumberFormatter
object or you can brute force check for an already existing decimal place mark (returning NO
if a decimal mark already exists).
I made the solution, that brings you control over decimal places count, so user can type only one decimal separator and you can also have a control over decimal places count.
Just set the decimalPlacesLimit value properly.
See the method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(@"text on the way: %@", string);
NSUInteger decimalPlacesLimit = 2;
NSRange rangeDot = [textField.text rangeOfString:@"." options:NSCaseInsensitiveSearch];
NSRange rangeComma = [textField.text rangeOfString:@"," options:NSCaseInsensitiveSearch];
if (rangeDot.length > 0 || rangeComma.length > 0){
if([string isEqualToString:@"."]) {
NSLog(@"textField already contains a separator");
return NO;
} else {
NSArray *explodedString = [textField.text componentsSeparatedByString:@"."];
NSString *decimalPart = explodedString[1];
if (decimalPart.length >= decimalPlacesLimit && ![string isEqualToString:@""]) {
NSLog(@"textField already contains %d decimal places", decimalPlacesLimit);
return NO;
}
}
}
return YES;
}
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if([string isEqualToString:@"."]) {
BOOL containsDecimal = [textField.text containsString:@"."];
return !containsDecimal;
}
return YES;
}
If textfield text already contains a '.' then return NO else return YES.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Allow to remove character (Backspace)
if string == "" {
return true
}
// Block multiple dot
if (textField.text?.contains("."))! && string == "." {
return false
}
// Check here decimal places
if (textField.text?.contains("."))! {
let limitDecimalPlace = 2
let decimalPlace = textField.text?.components(separatedBy: ".").last
if (decimalPlace?.count)! < limitDecimalPlace {
return true
}
else {
return false
}
}
return true
}
//Create this variable in .h file or .m file
float _numberOfDecimal;
//assign value in viewDidLoad method
numberOfDecimal = 2;
#pragma mark - TextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Allow to remove character (Backspace)
if ([string isEqualToString:@""]) {
return true;
}
// Block multiple dot
if ([textField.text containsString:@"."] && [string isEqualToString:@"."]) {
return false;
}
// Check here decimal places
if ([textField.text containsString:@"."]) {
NSString *strDecimalPlace = [[textField.text componentsSeparatedByString:@"."] lastObject];
if (strDecimalPlace.length < _numberOfDecimal) {
return true;
}
else {
return false;
}
}
return true;
}