How to enter Numbers only in UITextField and limit maximum length? - objective-c

In UITextField we Enter Numeric only and limit up to 3 numeric for this i used below code
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
while (newLength < CHARACTER_LIMIT) {
return [string isEqualToString:filtered];
}
/* Limits the no of characters to be enter in text field */
return (newLength > CHARACTER_LIMIT ) ? NO : YES;
}
When i press long press on textfield (like below image )and enter string between two numbers it's allowing all special characters and charterers also.

Not that I don't like the answer I wrote at this question, that was copy & pasted here also. I'll try to explain your error.
This answer is based on the assumption that your constants are defined something like this:
#define NUMBERS_ONLY #"1234567890"
#define CHARACTER_LIMIT 3
The reason your logic is failing is that you never handle the event when newLength will be equal to the CHARACTER_LIMIT.
To illustrate suppose your textfield is empty and you request to paste the string #"ABC" to the textfield, your delegate method is called. You create the string filtered which correctly evaluates to an empty string, and you can't wait to execute the line return [string isEqualToString:filtered]; but you never actually evaluate that line because you don't meet the entry requirements for the while loop, because newLength is 3. so the simple return (newLength > CHARACTER_LIMIT ) ? NO : YES; decides the return value.
If your CHARACTER_LIMIT is actually 4 for some reason, just imagine #"ABCD" as the string the logic still applies.
Here is a simple example of your function corrected to work. Again I'm assuming that CHARACTER_LIMIT is equal to 3.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return (([string isEqualToString:filtered])&&(newLength <= CHARACTER_LIMIT));
}

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
// Check for non-numeric characters
NSUInteger lengthOfString = string.length;
for (NSInteger loopIndex = 0; loopIndex < lengthOfString; loopIndex++) {
unichar character = [string characterAtIndex:loopIndex];
if (character < 48) return NO; // 48 unichar for 0
if (character > 57) return NO; // 57 unichar for 9
}
// Check for total length
NSUInteger proposedNewLength = textField.text.length - range.length + string.length;
if (proposedNewLength > 3) return NO;
return YES;
}
Its working fine for me u can use this code

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *s = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"^\\d{0,3}$" options:0 error:nil];
NSTextCheckingResult *match = [regex firstMatchInString:s options:0 range:NSMakeRange(0, [s length])];
return (match != nil);
}

Check the UITextFieldDelegate method
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
This method will be invoked each time after you type/tap a character or press cut/paste and before that action changes the characters displayed. Here you can very well to your check for maxLength and numbers-only text input(by using RegularExpression patter as given below) and return YES or NO basd on that. If you return YES it will do the change otherwise it will not. Hope this clears your doubt.

I prefer using an NSNumberFormatter to validate the text can be parsed into a number. NSNumberFormatter returns nil if the string cannot be converted to a number. This lets you react to the input (i.e. make text red, throw up a alert)
NSNumber* value = nil;
NSNumberFormatter* format = [[NSNumberFormatter alloc] init];
value = [format numberFromString:someValueString];//returns and
if (value == nil){
//do something useful i.e. show alert
}

Related

How to secure first digits and display last 3 digits?

I have text field and the data that i entered in text field has to be displayed on label with some secure text.
for example if i have entered 123456789 data in text field then the data in label must be shown as ******789.
How it can be done?
This is the solution for your query,
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString * textFieldString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSMutableString * str1 = [[NSMutableString alloc]initWithString:textFieldString];
if(str1.length > 3){
NSRange r = NSMakeRange(0, [str1 length] - 3);
[str1 replaceCharactersInRange:r withString:[[NSString string] stringByPaddingToLength:r.length withString:#"*" startingAtIndex:0]];
NSLog(#"test string---- > %#",str1);
}
}

Restricting NSTextField input to alpha-numeric

I'm making a simple app in which there is an NSTextField and I want only alpha-numeric characters in it while typing.
Can anyone suggest an approach to this please?
There's a built-in support for that.
In Interface Builder check "Only Roman Characters" option for the text field.
OR
In your code set this property:
[myTextField.cell setAllowedInputSourceLocales: #[NSAllRomanInputSourcesLocaleIdentifier]];
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([self validCharecter:textField.text){
return YES;
}
else{
return NO:
}
}
-(BOOL)validCharecter :(NSString)textStr{
NSCharacterSet *alphaSet = [NSCharacterSet alphanumericCharacterSet];
BOOL validStr = [[textStr stringByTrimmingCharactersInSet:alphaSet] isEqualToString:#""];
return validStr;
}
Try with dis hope it will helps you!!
Take a look at below code sample.
I hope this will help you.
//#define CHARACTERS #" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
//#define CHARACTERS_NUMBERS [CHARACTERS stringByAppendingString:#"1234567890"]
///// Inside shouldChangeCharactersInRange
///////////>>>>>>>>>>>>>>>>>>
if(textField== txtFldAlpha)
{
//Alpha only
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *unacceptedInput =
[[NSCharacterSet characterSetWithCharactersInString:CHARACTERS] invertedSet];
// Create array of strings from incoming string using the unacceptable
// characters as the trigger of where to split the string.
// If array has more than one entry, there was at least one unacceptable character
if ([[string componentsSeparatedByCharactersInSet:unacceptedInput] count] > 1)
return NO;
else
return YES&&(newLength < 26);
return YES;
}
///////////<<<<<<<<<<<<<<<<<<
///////////>>>>>>>>>>>>>>>>>>
if(textField==txtFldNumeric)
{
//Num only
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([[string componentsSeparatedByCharactersInSet:nonNumberSet] count] > 1)
return NO;
else
return YES&&(newLength < 6);
return YES;
}
///////////<<<<<<<<<<<<<<<<<<
///////////>>>>>>>>>>>>>>>>>>
if(textField==txtFieldNumAlphaSpecial)
{
//Num,Alpha,Special field
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 50) ? NO : YES;
}
///////////<<<<<<<<<<<<<<<<<<
#define ACCEPTABLE_CHARACTERS #" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return [string isEqualToString:filtered];
}
OR
Implement
textField:shouldChangeCharactersInRange:replacementString:
in the delegate, check the replacement string for special characters, and disallow the replacement if you detect any.
The easiest way to check for non-alphanumerics is as follows:
if ([replacementString rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
// There are non-alphanumeric characters in the replacement string
}
Hope this helps mate .. !

validate alphanumeric value in UITextField

I want alphanumeric value in textfield.If user enter only character or number then sending massage.Even no special characters acceptable.
NSString *str = askIdTxt.text;
NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet];
NSCharacterSet *numberSet = [NSCharacterSet decimalDigitCharacterSet];
BOOL isAlphaNumericOnly = [[str stringByTrimmingCharactersInSet:alphanumericSet] isEqualToString:#""] && ! [[str stringByTrimmingCharactersInSet:numberSet] isEqualToString:#""];
if (isAlphaNumericOnly) {
NSLog(#"isAplhaNumericOnly: %#",(isAlphaNumericOnly? #"Yes":#"No"));
}
This is always returning true. I am not getting what is wrong in this.
How about using regular expression:
-(BOOL)isAlphaNumericOnly:(NSString *)input
{
NSString *alphaNum = #"[a-zA-Z0-9]+";
NSPredicate *regexTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", alphaNum];
return [regexTest evaluateWithObject:input];
}
and then use it
if([self isAlphaNumeric:str])
{
NSLog(#"IT IS ALPHA NUMERIC STRING");
}
edit
The same technique can be used to validate passwords, you need only better regex:
-(BOOL)isPasswordStrong:(NSString *)password {
/*
8-20 chars
at least one letter
at least one number OR special character
no more than 3 repeated characters
*/
NSString *strongPass= #"^(?!.*(.)\\1{3})((?=.*[\\d])(?=.*[A-Za-z])|(?=.*[^\\w\\d\\s])(?=.*[A-Za-z])).{8,20}$";;
NSPredicate *regexTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", strongPass];
return [regexTest evaluateWithObject:password];
}
using the regular expression you can create different rules but this can give you a headstart,
Call this Method and modify it accordingly .....
-(BOOL) isPasswordValid:(NSString *)pwd
{
if ( [pwd length]<4 || [pwd length]>20 ) return NO; // too long or too short
NSRange rang;
rang = [pwd rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
if ( !rang.length ) return NO; // no letter
rang = [pwd rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];
if ( !rang.length ) return NO; // no number;
return YES;
}
I guess the problem is in the alphanumericCharacterSet, here is a part from doc:
Informally, this set is the set of all characters used as basic units
of alphabets, syllabaries, ideographs, and digits.
So, I am expecting it would allow the unwanted characters to you.
You may also try using Regex:
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"^[a-z\\d]+$" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger matches = [regex numberOfMatchesInString:str options:NSMatchingReportCompletion range:NSMakeRange(0, [str length])];
BOOL hasMatches = (matches > 0) && !error;
Try this
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSCharacterSet *charactersToBlock = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
return ([string rangeOfCharacterFromSet:charactersToBlock].location == NSNotFound);
}
Try this :
NSCharacterSet *blockedCharacters = [[[NSCharacterSet alphanumericCharacterSet] invertedSet] retain];
- (BOOL)textField:(UITextField *)field shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)characters
{
return ([characters rangeOfCharacterFromSet:blockedCharacters].location == NSNotFound);
}

NSNumberFormatter not allowing decimal input

If I enter a decimal point '.' into my UITextField, the number formatter called does not recognise the decimal point and continues as if the decimal point has not been entered. I.e If I entered 200.9, the decimal point would not show up in the textfield and the text of the textfield would be 2009.
I want to limit the number of digits after the decimal point to 2 as I believe I am doing below. Please can you tell me what I am doing to cause this?
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
BOOL isDeleting = [textField.text substringWithRange:range].length > string.length;
int index = [textFields indexOfObject:textField];
NSString *input;
if (isDeleting == NO)
input = [textField.text stringByAppendingString:string];
else {
NSMutableString *str = [textField.text mutableCopy];
[str deleteCharactersInRange:range];
input = [[str copy] autorelease];
[str release];
}
if ([input isEqualToString:#"£"] || ([input isEqualToString:#""] && index != 1)) {
[textField setText:#"£"];
}
else {
if (index != 1)
[textField setText:[self numberFormattedString:input]];
else
[textField setText:input];
}
return NO;
}
- (NSString *) numberFormattedString:(NSString *)str {
str = [str stringByReplacingOccurrencesOfString:#"£" withString:#""];
str = [str stringByReplacingOccurrencesOfString:#"," withString:#""];
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en-UK"];
[formatter setLocale:locale];
[locale release];
[formatter setAllowsFloats:YES];
[formatter setMaximumFractionDigits:3];
[formatter setMinimumFractionDigits:0];
[formatter setDecimalSeparator:#"."];
return [formatter stringFromNumber:[NSNumber numberWithFloat:[str floatValue]]];
}
TIA.
Let's say you enter the number 100 and then a decimal point. When numberFormattedString is called with the string £100., it's going to get rid of the £, and str will contain the string 100. which [str floatValue] converts to the float value 100, and finally your number formatter spits it back out as the string £100 without any decimal point. So basically [str floatValue] is killing your decimal point.
One solution is to check for when you get the decimal point as your replacement string in the text field delegate method, and skip calling numberFormattedString in that case. Then when the user enters the next digit, you can carry on calling numberFormattedString, and the conversion should happen correctly. You'll just have to make sure that the user can only enter one decimal point.
EDIT: I just realized that my suggested solution still won't work if you enter a 0 after the decimal point (e.g. 100.0), but I'm sure there is a minor tweak that you can figure out to solve that.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *numSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789."];
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
int charCount = [newString length];
if ([newString rangeOfCharacterFromSet:[numSet invertedSet]].location != NSNotFound
|| [string rangeOfString:#"."].location != NSNotFound
|| charCount > 15) {
return NO;
}
// if (charCount == 4 || charCount == 9 || charCount==13) {
// newString = [newString stringByAppendingString:#"."];
// }
NSLog(#"IN method");
textField.text = newString;
return NO;
}

Restrict user to only entering one word in UITextField

Is there a way to only allow the user enter one word in the UITextField? If so, how?
Here's the current code that I'm using:
-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
_disallowedCharacters = [NSCharacterSet whitespaceCharacterSet];
for(int i = 0; i < [_searchBox.text length]; i++){
unichar c = [_searchBox.text characterAtIndex:i];
if (![_disallowedCharacters characterIsMember:c])
{
return NO;
}
}
return YES;
}
Use the UITextFieldDelegate protocol:
- (BOOL) textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)textEntered
{
for (int i = 0; i < [textEntered length]; i++)
{
unichar c = [textEntered characterAtIndex:i];
if ([disallowedCharacters characterIsMember:c])
{
return NO;
}
}
return YES;
}
where disallowedCharacters is an NSCharacterSet containing the characters that should not be accepted by the keyboard, i.e. a space, punctuation, numbers, etc:
self.disallowedCharacters = [NSCharacterSet characterSetWithCharactersInString:#" ,.123"];
For a character set (for Evan's answer) that checks against whitespace and newlines, you can use
self.disallowedCharacters = [NSCharacterSet whitespaceAndNewlineCharacterSet];
If you want to check against characters besides whitespace and newlines, create a mutableCopy and add whatever you'd like to it:
NSMutableCharacterSet *set = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
[set formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
[set formUnionWithCharacterSet:[NSCharacterSet symbolCharacterSet];
[set addCharactersInString:#"whatever you want"];
...
self.disallowedCharacters = [[set copy] autorelease];
[set release];
The NSCharacterSet docs have a good overview of the character sets available to you.