Check that a input to UITextField is numeric only

How do I validate the string input to a UITextField? I want to check that the string is numeric, including decimal points.


You can do it in a few lines like this:

BOOL valid;
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text];
valid = [alphaNums isSupersetOfSet:inStringSet];    
if (!valid) // Not numeric

-- this is for validating input is numeric chars only. Look at the documentation for NSCharacterSet for the other options. You can use characterSetWithCharactersInString to specify any set of valid input characters.


There are a few ways you could do this:

  1. Use NSNumberFormatter's numberFromString: method. This will return an NSNumber if it can parse the string correctly, or nil if it cannot.
  2. Use NSScanner
  3. Strip any non-numeric character and see if the string still matches
  4. Use a regular expression

IMO, using something like -[NSString doubleValue] wouldn't be the best option because both @"0.0" and @"abc" will have a doubleValue of 0. The *value methods all return 0 if they're not able to convert the string properly, so it would be difficult to distinguish between a legitimate string of @"0" and a non-valid string. Something like C's strtol function would have the same issue.

I think using NSNumberFormatter would be the best option, since it takes locale into account (ie, the number @"1,23" in Europe, versus @"1.23" in the USA).


I use this code in my Mac app, the same or similar should work with the iPhone. It's based on the RegexKitLite regular expressions and turns the text red when its invalid.

static bool TextIsValidValue( NSString* newText, double &value )
{
    bool result = false;

    if ( [newText isMatchedByRegex:@"^(?:|0|[1-9]\\d*)(?:\\.\\d*)?$"] ) {
        result = true;
        value = [newText doubleValue];
    }
    return result;
}

- (IBAction) doTextChanged:(id)sender;
{
    double value;
    if ( TextIsValidValue( [i_pause stringValue], value ) ) {
        [i_pause setTextColor:[NSColor blackColor]];
        // do something with the value
    } else {
        [i_pause setTextColor:[NSColor redColor]];
    }
}

If you want a user to only be allowed to enter numerals, you can make your ViewController implement part of UITextFieldDelegate and define this method:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
  NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];

  // The user deleting all input is perfectly acceptable.
  if ([resultingString length] == 0) {
    return true;
  }

  NSInteger holder;

  NSScanner *scan = [NSScanner scannerWithString: resultingString];

  return [scan scanInteger: &holder] && [scan isAtEnd];
}

There are probably more efficient ways, but I find this a pretty convenient way. And the method should be readily adaptable to validating doubles or whatever: just use scanDouble: or similar.