Kex
Kex

Reputation: 8589

How to restrict UITextField to a defined set of characters and limit the length?

I am working on a login and resister view controller. I am limiting usernames to 12 characters and passwords to 16 using :

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range   replacementString:(NSString *)string
{

  if(textField==self.userField){

      NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
      return !([newString length] > 12);
    }

    else if(textField==self.passwordField){
        NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
        return !([newString length] > 16);

    }

    return YES;

}

this works well but I also want to limit it to a set of characters to stop unwanted symbols and also Chinese characters. I want to define this set:

#define ACCEPTABLE_CHARACTERS @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

Not sure how to add it to the method above though and get both working. If I was to check for the character set only and not length the code would be:

- (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];
}

Not sure how to combine them though. Can someone help me please? Thanks!

Upvotes: 0

Views: 1196

Answers (3)

Gene Myers
Gene Myers

Reputation: 1270

I know this has already been answered, but I had a similar scenario and I found none of the answers on StackOverflow handled the Backspace character.

I needed to limit input into a UITextField to a specific number of AlphaNumeric characters, but be able to enter spaces.

Also, using [textField length] > kMAXNUMCHARS caused a problem: you couldn't backspace once you hit the max number of chars.

So here's my complete solution. It also disallows leading spaces. Trailing spaces are trimmed elsewhere when the value is saved (in my case to a PLIST file)

In my Constants.h file I defined:

#define ALLOWED_CHARECTERS @" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
extern const int kMAXUSERNAMELENGTH;

then in Constants.m:

const int kMAXUSERNAMELENGTH = 9;

I define my class as UITextFieldDelegate with the line

[self._txtUsername.textField  setDelegate:self];

Don't forget to declare the UITextFieldDelegate protocol in your class definiion

@interface MyClass : CCNode <UITextFieldDelegate>

And finally,

    //UITextFiledDelegate Protocol method
    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

        //disallow leading spaces. must allow trailing spaces- never know if we'll add another char
        //we trim trailing spaces when we save the TextField value, in our case to  Plist file
        if (range.location == 0 && [string isEqualToString:@" "]) 
            return NO;

        //we use defined ALLOWED_CHARECTERS so we can add chars later, easily. 
        //we could use [NSCharacterSet alphanumericCharacterSet] if we don't need to allow spaces
        NSCharacterSet *allowedInput = [NSCharacterSet characterSetWithCharactersInString:ALLOWED_CHARECTERS];
        NSArray* arChar = [string componentsSeparatedByCharactersInSet:allowedInput]; //arChar.count = 1 if 'allowedInput' not in 'string'

        //disallow input if its not a backspace (replacementString paramater string equal @"" if a backspace) AND
        //(disallow input >= kMAXUSERNAMELENGTH chars, OR disallow if not in allowed allowedChar set
        if ( ![string isEqual:@""]  && (  [textField.text length] >= kMAXUSERNAMELENGTH || !([arChar count] > 1)) ) 
             return NO;

        return YES;

    }

I hope this helps someone.

Upvotes: 0

Midhun MP
Midhun MP

Reputation: 107131

You can do it like (I divided it to function for more readability and easy to scale the conditions)

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    return ([self checkLengthOfString:newString inField:textField] && [self checkCharacter:newString]);
}


// Check Length
- (BOOL)checkLengthOfString:(NSString *)text inField:(UITextField *)textField
{
   if(textField == self.userField)
   {
      return !([text length] > 12);
   }
   else if(textField == self.passwordField)
   {
      return !([text length] > 16);
   }
}

// Check character
- (BOOL)checkCharacter:(NSString *)text
{
    BOOL status        = YES;
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
    NSRange r          = [text rangeOfCharacterFromSet:s];
    if (r.location != NSNotFound)
    {
       status = NO;
    }
    return status;
}

Upvotes: 1

Michael
Michael

Reputation: 1030

Why don't you just use a regEx to match that chars?

Upvotes: 0

Related Questions