I want to have runtime validation on my UITextField, i.e. when user starts entering data, it should validate and pop up error message if not correct. How do I implement this feature ?
textfieldDidChange or textFieldShouldEndEditing can be of any help ?
Any tutorial ?
You can implement the textField:shouldChangeCharactersInRange:replacementString: method on your text field's delegate, rejecting any characters that are invalid for your textfield. See the UITextFieldDelegate protocol reference for more information.
For example, if you only want to allow entry of decimal numbers, you could use:
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0);
}
This won't actually pop up an error message if the input is incorrect; instead, it will prevent entry of characters that are incorrect.
If you do want to allow the user to type invalid characters, and them give them an error, you could implement this in the textFieldShouldEndEditing: method of your delegate.
This is a better solution since it allows backspaces.
Taken from :Hugo Larcher's blog
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *nonNumberSet;
if (textField == self.priceField) //allow decimals
nonNumberSet=[[NSCharacterSet characterSetWithCharactersInString:#"0123456789."] invertedSet];
else
nonNumberSet=[[NSCharacterSet characterSetWithCharactersInString:#"0123456789"] invertedSet];
// allow backspace
if (range.length > 0 && [string length] == 0) {
return YES;
}
// do not allow . at the beggining
if (range.location == 0 && [string isEqualToString:#"."]) {
return NO;
}
// set the text field value manually
NSString *newValue = [[textField text] stringByReplacingCharactersInRange:range withString:string];
newValue = [[newValue componentsSeparatedByCharactersInSet:nonNumberSet] componentsJoinedByString:#""];
textField.text = newValue;
// return NO because we're manually setting the value
return NO;
}
Related
I am having 4 text fields in which I want to put two limitations simultaneously. One is that the user should be able to type in only capital letters with the maximum character limit to 2 only. My code for this is as follows:-
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
// Below logic is for All 4 Modifer Textfields
// we are restrict the user to enter only max 2 characters in modifier textfields.
if (textField==txt_modifier1 || textField==txt_modifier2 || textField==txt_modifier3 ||
textField==txt_modifier4) {
textField.text = [textField.text stringByReplacingCharactersInRange:range
withString:[string
uppercaseStringWithLocale:[NSLocale currentLocale]]];
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 2) ? NO : YES;
}
return YES;
}
this is not functioning properly as it is appending one more character as I type in any character and also not limiting the number of characters to 2. Please suggest a way to tackle this problem.
You're manually updating the text in your textfield and then sending YES back (which then appends the characters a second time). Then, you're usingthe new text with the replacement string to compare it to two (which, then appends your characters again) ...
Try this:
if (...) {
NSString *result = [textField.text stringByReplacingCharactersInRange:range
withString:string.uppercaseString];
if (result.length <= 2)
textField.text = result;
return NO;
}
return YES;
For limiting the number of characters and capitalizing it in your UITextField, use this code block
-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
textField.text = [textField.text capitalizedString];
if(textField.text.length >= 3 && range.length == 0)
{
return NO;
}
else
{
return YES;
}
Please try to use this one ...It may help you
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([string isEqualToString:[string capitalizedString]])
{
NSString *result = [textField.text stringByReplacingCharactersInRange:range
withString:string.uppercaseString];
if (result.length <= 2)
textField.text = result;
return NO;
}
else
return YES;
}
loginUITextFieldTextDidChangeNotificationMake judgment here
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(textChanged:)
name:UITextFieldTextDidChangeNotification
object:YOUR_TEXT_FIELD];
-(void)textChanged:(NSNotification *)notif {
//to do your logic
}
I'm using the following method to filter out non numeric characters when the user is entering content on the textfield:
#define NUMBERS #"0123456789"
- (BOOL)textField:(UITextField *)textFieldBeingChanged shouldChangeCharactersInRange:(NSRange) range replacementString:(NSString *)string
{
NSCharacterSet *cs;
NSString *filtered;
// Check for period
if ([textFieldBeingChanged.text rangeOfString:#"."].location == NSNotFound)
{
cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS] invertedSet];
filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return [string isEqualToString:filtered];
}
}
However it blocks out the keyboard Return key as well, meanning by pressing the "return" key the
code to resignFirstResponder is not being called. Any way to resolve this? How should i check if the 'return' keywas pressed?
Thanks
A
I am trying to create a questionnaire, in which the user shall rate statements from 1-7.
The user rates the statements by filling UITextFields with a value between 1-7.
I have made it so that the user can only write in values between 1-7 and that they only can write one character per textfield.
What I want to do now is to prevent the user from using that value more than once.
This is the code that I have so far.
#define CHARACTERS #"1234567"
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
// These are the characters that are ~not~ acceptable
NSCharacterSet *unacceptedInput = [[NSCharacterSet characterSetWithCharactersInString:CHARACTERS] invertedSet];
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (([[string componentsSeparatedByCharactersInSet:unacceptedInput] count] >1 ) | ([newString length] > 1) )
return NO;
else
return YES;
}
I would use a dictionary. Whenever a number is chosen in a textfield, check if the dictionary has that value. If it doesn't have the value, the value entered is correct. Add the entry into the dictionary now and then let the user proceed to the next textfield. If you repeat this process for all the textfields you will be able to solve this problem pretty easily.
You can do one thing give tag to all textfields and check whether string you entered in current textfield is same as text of all other textfields then return NO.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
// These are the characters that are ~not~ acceptable
NSCharacterSet *unacceptedInput = [[NSCharacterSet characterSetWithCharactersInString:CHARACTERS] invertedSet];
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (([[string componentsSeparatedByCharactersInSet:unacceptedInput] count] >1 ) | ([newString length] > 1) )
return NO;
else
//Call function to check if string is same as other textfield.text then return NO else YES
}
else
another option is you can take 1 string and save textfield.text in that string and update all time when you enter and check with it whether the string you are entering is in substring of that string.
best of luck
At the time of creating UITextField set the keyboardType as UIKeyboardTypeNumberPad.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([[textField text]length]==1)
//perform condition
else
//perform condition
}
this might help
i want to validate a text field to accept only characters while typing in it.....
I use the following for integers but I guess you could easily modify it to scan for strings/chars (see NSScanner):
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];
// This allows backspace
if ([resultingString length] == 0) {
return true;
}
NSUInteger holder;
NSScanner *scan = [NSScanner scannerWithString: resultingString];
return [scan scanInteger: &holder] && [scan isAtEnd];
}
Don't forget to set the UITextField delegate appropriately :)
I have a UITextField in my IB and I want to check out if the user entered only numbers (no char)and get the integer value.
I get the integer value of the UITextField like that :
int integer = [myUITexrtField.text intValue];
When I put a character ( , ; . ) it return me 0 and I don't know how to detect that it is not only numbers.
How can I do?
Implementing shouldChangeCharactersInRange method as below does not allow the user input non-numeric characters.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0) || [string isEqualToString:#""];
}
This returns YES if the string is numeric, NO otherwise. the [string isEqualToString#""] is to support the backspace key to delete.
I love this approach because it's clean.
Be sure to set your text field delegate
Use the following function to ensure user can type in numbers only:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber* candidateNumber;
NSString* candidateString = [textField.text stringByReplacingCharactersInRange:range withString:string];
range = NSMakeRange(0, [candidateString length]);
[numberFormatter getObjectValue:&candidateNumber forString:candidateString range:&range error:nil];
if (([candidateString length] > 0) && (candidateNumber == nil || range.length < [candidateString length])) {
return NO;
}
else
{
return YES;
}
}
Try this: It will stop user to enter any character other then numbers
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([string rangeOfCharacterFromSet:nonNumberSet].location != NSNotFound)
{
return NO;
}
return YES;
}
http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Objective-C
Or you could ensure that only the numeric keyboard appears when the focus comes on the field
To only allow for numeric input:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
return [string isEqualToString:#""] ||
([string stringByTrimmingCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].length > 0);
}
To test for an integer:
- (BOOL)isNumeric:(NSString *)input {
for (int i = 0; i < [input length]; i++) {
char c = [input characterAtIndex:i];
// Allow a leading '-' for negative integers
if (!((c == '-' && i == 0) || (c >= '0' && c <= '9'))) {
return NO;
}
}
return YES;
}
Answer by #devsan is incorrect. If a user pastes anything with a a number such as "1abc" her code would break
It should be (allow replacement only if all the chars are digits):
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
return ([string stringByTrimmingCharactersInSet:nonNumberSet].length == string.length) || [string isEqualToString:#""];
}
You could also use UITextFieldDelegate method
textField:shouldChangeCharactersInRange:replacementString:
to live check that each time the user press a key, it is a simple digit, so that he/she knows that only int value is to be entered in the field.
Want to allow negative numbers as well?
Elaborating on davsan's answer, here is a solution that supports entering negative as well as positive numbers, and disallows anything else.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0) || [string isEqualToString:#""] || ([textField.text isEqualToString:#""] && [string isEqualToString:#"-"]);
return YES;
}
This code is work with localisation too .
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([string isEqualToString:#""]) return YES;
NSCharacterSet *characterSet = nil;
characterSet = [NSCharacterSet decimalDigitCharacterSet];
NSRange location = [string rangeOfCharacterFromSet:characterSet];
return (location.location != NSNotFound);
if(characterSet == nil) return YES;
return YES;
}