Search code examples
iosuitextfielduikeyboardnscharacterset

UITextField - Prevent user from typing non-standard characters (like Emoticons)


My app creates and stores EKEvents into the standard Calendar database, however, I've found that if I use an emoticon as the "notes" for an event, it causes a crash when trying to read the event out of the Calendar.

I don't want or need the use of emoticons in the event.notes. I just happened to be testing and was kind of shocked when it let me save the event. (The emoticons even show up in the Calendar itself)

So I think my problem can be solved one of 2 way, neither of which I've been able to figure out.

1) Can I disable or hide the custom keyboard button? <--I'd prefer this solution

enter image description here

2) If not, how do I create a character set that includes all of the possible characters in all of the standard keyboards to check against when making sure the user does not type an emoticon?

I've tried using some of the standard character sets to check against, like alphanumericCharacterSet, but using that, I can't type in spaces.

Here's the code I'm using so far, to check against the character the user is typing:

- (BOOL)textField:(UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (string.length == 0) {
        return YES;
    }

    NSCharacterSet *myCharSet = [NSCharacterSet alphanumericCharacterSet];
    for (int i = 0; i < [string length]; i++) {
        unichar c = [string characterAtIndex:i];
        if ([myCharSet characterIsMember:c]) {
            return YES;
        }
    }

    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Invalid Input" message:@"Oops! You can't use that character." delegate:self cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
    [av show];
    return NO;
}

EDIT: Clarification on the error

There is no error, only a crash. My app saves calendar events, and displays them in a list to the user. The user can then mark the event as "Paid" or "Unpaid" at which time I append a string to the .notes property of the event " - Paid". This is so when I reload the table, if the event is paid, it displays a specific icon to the user. The crash happens when the saved even has an emoticon as the .notes property, and I try to append the .notes.


Solution

  • You can combine NSCharacterSets using a union to add more allowable characters:

        NSMutableCharacterSet *myCharSet = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
        [myCharSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet];
    

    Here is the list of available character sets to choose from:

    controlCharacterSet
    whitespaceCharacterSet
    whitespaceAndNewlineCharacterSet
    decimalDigitCharacterSet
    letterCharacterSet
    lowercaseLetterCharacterSet
    uppercaseLetterCharacterSet
    nonBaseCharacterSet
    alphanumericCharacterSet
    decomposableCharacterSet
    illegalCharacterSet
    punctuationCharacterSet
    capitalizedLetterCharacterSet
    symbolCharacterSet
    newlineCharacterSet
    

    Also, your code is checking to make sure any character is not outside the set; I think your intention is to check that all characters are not outside the set. (This only applies when the user enters more than one character at once - think copy and paste).

    Consider adjusting your loop to look more like this:

    NSCharacterSet *myCharSet = [NSCharacterSet alphanumericCharacterSet];
    for (int i = 0; i < [string length]; i++) {
        unichar c = [string characterAtIndex:i];
        if ([myCharSet characterIsMember:c] == NO) {
            // add your user alert here
            return NO;
        }
    }
    

    This way your loop won't simply exit on the first good character it finds; instead, it will exit on the first bad character.