Editing textfield after "endEdit" with ShouldChangeCharactersInRange implemented - ios

I have the following code implemented to restrict my user to enter in more than 2 decimal points and places after they have entered the first one. Users can still edit the textfield as long as they don't "leave" or "endEdit" the textfield. However, once they leave the textfield and go back, the textfield is not editable. How can I solve this problem?
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.SalesAmounttext)
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = #"^([0-9]+)?(\\.([0-9]{1,2})?)?$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression
options:NSRegularExpressionCaseInsensitive
error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString
options:0
range:NSMakeRange(0, [newString length])];
if (numberOfMatches == 0)
return NO;
}
return YES;
}

All I had to do was add in the clearsOnInsertion code and everything works! Thanks to #Wain
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.SalesAmounttext)
{
textField.clearsOnInsertion=YES ; // HERE
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = #"^([0-9]+)?(\\.([0-9]{1,2})?)?$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression
options:NSRegularExpressionCaseInsensitive
error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString
options:0
range:NSMakeRange(0, [newString length])];
if (numberOfMatches == 0)
return NO;
}
return YES;
}

Your logic places very tight restrictions on the user so any arbitrary edit will not be permitted. From a user standpoint that will probably be quite confusing so good options would be:
Set clearsOnInsertion when the text field is created so that each edit is a fresh start
Alert the user about invalid edits
Allow each edit and then format at the end of editing and alert the user to any issue then

Related

Regex in iOS to limit a text field to only letters and single apostrophies

After a text field is returned I want to check if the text provided is valid. Valid means only letters or a single apostrophe, for names.
I'm pretty new to regular expressions. Is there a simple regular expression I can use for this check, or can someone point me towards some reading material where I can learn to compose a regular expression that will fit my needs?
You can do it like this, but you need to show an error in case the input is invalid.
- (BOOL)textFieldShouldEndEditing:(UITextField *)aTextField
{
NSString *const regularExpression = #"^[a-zA-Z']+$";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regularExpression
options:kNilOptions
error:&error];
if (error) {
// Handle error
}
NSUInteger numberOfMatches = [regex numberOfMatchesInString:aString
options:0
range:NSMakeRange(0, [aString length])];
return numberOfMatches > 0;
}
The regx should be
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
you can use
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if (textField == emailid) {
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:#"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'"] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
;
return [string isEqualToString:filtered];
}
}
You can use the function that checks whether the input should be inserted or not and restrict the characters there. Since your restriction is fairly simple there is no need of regular expressions and you can use characters sets.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSMutableCharacterSet *allowedCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
[allowedCharacters addCharactersInString:#"'"];
if([string rangeOfCharacterFromSet:allowedCharacters.invertedSet].location == NSNotFound){
return YES;
}
return NO;
}

Input mask Textfield with Regex

I try to create an input mask for an UITextField for enter aircraft callsign. The mask should be "F-" and 4 letters. I try it with regular expression but it doesn't work fine. I show you my code. It is impossible to enter any character with it.
if (textField==_tImmat) {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = #"^(F-)([A-Z]{4})$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
if (numberOfMatches == 0){
return NO;
}
Any ideas to create regex which works fine for a string value like this :"F-XXXX" where X is an uppercase letter?
Thanks for your help...
I'm guessing that code is in your shouldChangeCharactersInRange method?
If so, because you are imposing of this specific format, no other string can ever be entered, i.e. unless the value of newString is F-<4 LETTERS>, the method will return NO.
So you can either move your validation to textFieldShouldReturn method:
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSString *expression = #"^(F-)([A-Z]{4})$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:textField.text options:0 range:NSMakeRange(0, [textField.text length])];
if (numberOfMatches == 0)
{
NSLog(#"wrong format!");
}
else
{
NSLog(#"correct format!");
}
return NO;
}
(by the way, for options you are using NSRegularExpressionCaseInsensitive which means it will allow user to put in both uppercase and lowercase characters and validate them as correct)
If you'd like to validate as the user types and restrict input of illegal characters, I'd change your code to something like this:
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
switch (newString.length)
{
case 0:
//allow user empty string
return YES;
case 1:
//check that first character is F
return [newString isEqualToString:#"F"];
case 2:
//check that the second character is -
return [newString isEqualToString:#"F-"];
case 3 ... 6:
//this will check the last four characters based on your regex
{
NSString *expression = #"^(F-)([A-Z]{0,4})$"; //notice the added range
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
if (numberOfMatches == 0)
{
return NO;
}
else
{
return YES;
}
}
default:
//in all other cases validation will fail
return NO;
}
Your validation only accepts the value F-XXXX. Starting with a black text field if the user enters the F, your validation fails because it's not F-XXXX.
You need to let the user enter each character and only fail the validation if the entered text can't possibly ever match the pattern.
There's no reason to use a regular expression for this. Just scan newString. Make sure it starts with an F. If the length is 2 or more, check that the 2nd character is a ```. Then simply make sure the length is less than 6 and the last few characters are the letters A-Z.

Allow only 2 whitespace in text

I have a UITextField and I want to allow user enter in this field maximum 2 whitespace. How I can do it?
I think I need to check something here:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {}
But what to check? I have searched the web, but nothing found.
You want to use a regular expression for this. The expression \s\s+ means two or more spaces, carriage returns or tabs.
NSString *text = textField.text;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:
#"(\s\s+)" options:0 error:nil];
[regex replaceMatchesInString:str options:0 range:NSMakeRange(0, [str length]) withTemplate:#" "];
textField.text = text;
This will return how many spaces there are in the string
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
int numberOfSpaces = [[textField.text componentsSeparatedByString:#" "] count];
if (numberOfSpace > 2) {
//notify user that he/she has too many spaces
}
}
Also you seem new to iOS. Don't forget to set your view controller as a UITextField delegate.

uitextfield how to parse the NSString

I am new to iOS.
I have a UITextField where I am adding values like: 1234, 54678, 8976
In the method shouldChangeCharactersInRage i want to take everytime the nsstring after , .
Meaning if i am adding : 1234 in my NSString I want to have 1234
If I have 1234, 5 in my NSStringg i will only have 5
Here is the code I have so far:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *getNo=[textField.text stringByReplacingCharactersInRange:range withString:string];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\ .*?," options:0 error:NULL];
NSArray *matches = [regex matchesInString:getNo options:0 range:NSMakeRange(0, [getNo length])];
NSTextCheckingResult *match = [matches lastObject];
if (match!=nil){
getNo=#"";
}
The problem in this case is the fact that IN THE FOLLOWING CASE: 1234, 65 instead of having 65 in my getNo, I will have an empty object.
How to solve this?
Try this.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *textFieldString=[textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *subStrings = [textFieldString componentsSeparatedByString:#","];
NSString *lastNumberString = [subStrings lastObject];
NSString *trimmedString = [lastNumberString stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]];
return YES;
}
Try this
NSArray *subStrings = [textFieldTextString componentsSeparatedByString:#","]; //this will returns array of strings separated by ,
double answer = [[subStrings lastObject] doubleValue];//get last value and type cast it

textField validation on real time in objective-C

I have a TextField in xCode and someone ask me to admit just certain types of characters giving me this text string:
^([A-ZÑÑÁÉÍÓÚÀÈÌÒÙÄËÏÖÜ ])*$
or this one:
^([0-9])*$
I Know a method using UITextFieldDelegate named textField shouldChangeCharactersInRange and this is the way I implement this method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *allowedCharacters = #"abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMÑNOPQRSTUVWXYZ0123456789.#-_ ";
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:allowedCharacters];
if ([string stringByTrimmingCharactersInSet:characterSet].length == 0)textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
return NO;
return YES;
}
if you see, on my programming my variable allowedCharacters stores all my valid characters but is in a different format (I have to write all the allowed characters),
I want to program something similar but with my partner's text format ^([0-9])*$ (text using ranges) how do I do that
Thanks in advance
you can use this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// Valida el patron que se introduce en el campo de texto
if (![self validateString:string withPattern:#"^([A-Z0-9.#-_ ])*$"]) return NO;
return YES;
}
in the withPattern parameter insert your regex expression, and then here it is the method which does all the magic:
- (BOOL)validateString:(NSString *)string withPattern:(NSString *)pattern
{
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
NSAssert(regex, #"Unable to create regular expression");
NSRange textRange = NSMakeRange(0, string.length);
NSRange matchRange = [regex rangeOfFirstMatchInString:string options:NSMatchingReportProgress range:textRange];
BOOL didValidate = NO;
// Did we find a matching range
if (matchRange.location != NSNotFound) didValidate = YES;
return didValidate;
}
test it and tell us how did it go

Resources