Restricting NSTextField input to alpha-numeric - objective-c

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 .. !

Related

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);
}

Anagram / partial anagram detection algorithm finds incorrect answers

I've written the following method to find out whether a long word contains a shorter word, and the order in which I pass the letters appears to effect the outcome.
I've noticed that if I feed it absconds and bassy it correctly reports NO, but if I alphabetize the letters and give it abcdnoss and abssy, it gives YES. I'm not too sure why this is – can anyone spot the issue?
- (BOOL) does: (NSString* ) longWord contain: (NSString *) shortWord {
while([longWord length] > 0 && [shortWord length] > 0) {
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString: [shortWord substringToIndex: 1]];
if ([longWord rangeOfCharacterFromSet: set].location == NSNotFound) {
return NO;
}
longWord = [longWord substringFromIndex: [longWord rangeOfCharacterFromSet: set].location+1];
shortWord = [shortWord substringFromIndex: 1];
}
return YES;
}
The problem with your algorithm is that this line doesn't work:
longWord = [longWord substringFromIndex: [longWord rangeOfCharacterFromSet: set].location+1];
If the first letter you search is at the end of the long word, then long word becomes an empty string, and you jump out of your loop to YES.
I would use a different algorithm, like this. I think it's easier to see what's going on, and so less prone to errors:
- (BOOL) does: (NSString* ) longWord contain: (NSString *) shortWord {
NSMutableString *longer = [longWord mutableCopy];
for (int i = 0; i<shortWord.length; i++) {
NSString *letter = [shortWord substringWithRange:NSMakeRange(i, 1)];
NSRange letterRange = [longer rangeOfString:letter];
if (letterRange.location != NSNotFound) {
[longer deleteCharactersInRange:letterRange];
}else{
return NO;
}
}
return YES;
}
- (BOOL) does: (NSString* ) longWord contain: (NSString *) shortWord
{
return ([longWord rangeOfString:shortWord].location != NSNotFound);
}

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

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
}

Objective-C: Numbers only text field? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Iphone UITextField only integer
I want to place a text field that only accepts numbers (0-9, doesn't even need decimals), but even using the "Number Pad" entry option I still get a keyboard with various symbols on it. Is there a better control for this, is there a better control for what I'm doing, or do I just have to validate input manually?
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
/* for backspace */
if([string length]==0){
return YES;
}
/* limit to only numeric characters */
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
for (int i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if ([myCharSet characterIsMember:c]) {
return YES;
}
}
return NO;
}
The code is somehow incorrect, should be
/* limit to only numeric characters */
NSCharacterSet* numberCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
for (int i = 0; i < [string length]; ++i)
{
unichar c = [string characterAtIndex:i];
if (![numberCharSet characterIsMember:c])
{
return NO;
}
}
return YES;
The following code will allow you to only input numbers as well as limit the amount of characters that can be used.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
/* limit to only numeric characters */
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
for (int i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if ([myCharSet characterIsMember:c]) {
return YES;
}
}
/* limit the users input to only 9 characters */
NSUInteger newLength = [customTextField.text length] + [string length] - range.length;
return (newLength > 9) ? NO : YES;
}

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.