6

I have a signup view controller where the user needs to enter an email address, a username, and a password.

For the username and password fields, right now you can currently sign up with a username like "user%$&" and a password like "password%^&$". I don't want people to be able to use these special characters.

I want to make it so that the username and password fields can only be submitted with alphanumeric characters aka letters and numbers. I have found some methods to do this, but they are confusing and I need this to work specifically with my code.

Here is some of the code that I perform when a user has entered an email, username, and password and they press the submit button:

NSString *user = [_usernameEntry text];
NSString *pass = [_passwordEntry text];
NSString *email = [_emailEntry text];

self.userSubmittedUsername = user;

if ([user length] < 4 || [pass length] < 4) {

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Invalid Entry" message:@"Username and Password must both be at least 4 characters long." delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];

    [alert show];

} else if ([email length] < 8) {

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Invalid Entry" message:@"Please enter your email address." delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];

    [alert show];

} else {

I would just like to add another else if into the above code and have it show an alert view if there are any characters that are NOT letters or numbers.

Thanks.

user3344977
  • 3,454
  • 4
  • 29
  • 82
  • 5
    Please, please don't restrict your passwords to such limited characters. Let the user enter secure passwords. – rmaddy Mar 08 '14 at 04:12
  • 3
    And why not do the filtering of invalid characters during data entry? Prevent the invalid characters in the text field delegate method `textField:shouldChangeCharactersInRange:replacementString:`. – rmaddy Mar 08 '14 at 04:13
  • rmaddy I just had an "aha" moment thanks to your comment. An app I was using today had the @ sign on the keyboard, but if you tapped it, it didn't add anything to the UITextField. Is this what you're talking about with your second comment? If it is then please post your solution in code and I'll implement it right away. Thanks! – user3344977 Mar 08 '14 at 04:15

4 Answers4

16

If you really want to restrict user from entering special characters, then probably the best way is to use shouldChangeCharactersInRange: method

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if(textField==YOUR_USER_NAME_TEXTFIELD || textField == YOUR_PASSWORD_TEXTFIELD)
    {

        NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"];
        for (int i = 0; i < [string length]; i++)
        {
            unichar c = [string characterAtIndex:i];
            if (![myCharSet characterIsMember:c])
            {
                return NO;
            }
        }

        return YES;
    }

    return YES;
}

This will restrict the user from entering the special characters. As rmaddy pointed out, it is always good to do this kind of validation when data entry happens.

PS: Make sure you set the delegate for your textfields.

GenieWanted
  • 4,315
  • 3
  • 20
  • 35
14

If anyone ends up here looking for a quick way in Swift to do this, here's my solution (where the UITextField allows uppercase letters, lowercase letters, numbers and spaces.)

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    let set = NSCharacterSet(charactersInString: "ABCDEFGHIJKLMONPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ").invertedSet
    return string.rangeOfCharacterFromSet(set) == nil

}

If it weren't for the space, you could simply use

let set = NSCharacterSet.alphanumericCharacterSet().invertedSet

On each key-press, we check if the character entered is contained in our sample set, if not, we return false.

schnabler
  • 508
  • 6
  • 20
  • Isn't the user still allowed to copy-paste input with this solution? – Teodor Ciuraru Nov 23 '17 at 11:38
  • You can also combine sets or add/remove characters. So you could do something like ``` var set = CharacterSet.alphanumerics set.insert(charactersIn: " ") set.invert() ``` – Saren Inden Jul 27 '20 at 09:27
7

Some more good and better way,

Good way

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)characters
{
    if(textField.tag == yourTextFieldTag) {
        NSCharacterSet *allowedCharacters = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
        return ([characters rangeOfCharacterFromSet:allowedCharacters].location == NSNotFound);
    }
    return YES;
}

Better way

Note, even you can make it memory efficient by declaring NSCharacterSet *allowedCharacters in .h file (header file), and in viewDidLoad you can write this,

allowedCharacters = [[NSCharacterSet alphanumericCharacterSet] invertedSet];

then you can use it like this,

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)characters
{
    if(textField.tag == yourTextFieldTag) {
        return ([characters rangeOfCharacterFromSet:allowedCharacters].location == NSNotFound);
    }
    return YES;
}
Community
  • 1
  • 1
Hemang
  • 25,740
  • 17
  • 113
  • 171
3

Though it's late to answer and there are other simple and great approaches, but this answer might be useful to someone.

This is simple and worked like a charm for me.

Swift 3:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    /// 1. replacementString is NOT empty means we are entering text or pasting text: perform the logic
    /// 2. replacementString is empty means we are deleting text: return true
    if string.characters.count > 0 {
        var allowedCharacters = CharacterSet.alphanumerics

        let unwantedStr = string.trimmingCharacters(in: allowedCharacters)
        return unwantedStr.characters.count == 0
    }

    return true
}

Note: This will work for pasting strings into the text field as well. Pasted string will not be displayed in text field if it contains any unwanted characters.

Rishi
  • 549
  • 4
  • 13