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

- 63,694
- 13
- 151
- 195

- 11,962
- 23
- 81
- 107
22 Answers
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.

- 22,706
- 18
- 63
- 99

- 1,470
- 2
- 11
- 6
-
22this answer does not check doubles or punctuation – zambono Nov 10 '11 at 16:20
There are a few ways you could do this:
- Use NSNumberFormatter's numberFromString: method. This will return an NSNumber if it can parse the string correctly, or
nil
if it cannot. - Use NSScanner
- Strip any non-numeric character and see if the string still matches
- 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).

- 242,470
- 58
- 448
- 498
-
Hmmm, I must be setting the options incorrectly for NSNumberFormatter. When I use numberFromString using the string "34jfkjdskj80" it will return the number 3480. It seems to just strip the characters instead of returning nil. – Tony Eichelberger Sep 02 '09 at 18:40
-
5@Tony yeah I'm not sure what you're doing, because the following logs "N: (null)" for me: `NSNumberFormatter * f = [[NSNumberFormatter alloc] init]; NSNumber * n = [f numberFromString:@"34jfkjdskj80"]; NSLog(@"N: %@", n);` – Dave DeLong Sep 02 '09 at 20:21
-
Thank you. I will double check and compare against your code. – Tony Eichelberger Sep 02 '09 at 21:06
-
Well, I copied in your example and ran it, now I get "N: 34"? Strange. This is on the iPhone SDK 3.0.1 if that matters. – Tony Eichelberger Sep 02 '09 at 21:11
-
@Dave - I think I figured it out. Let me know if this sounds correct. I changed the formatter behavior to NSNumberFormatterBehavior10_0 and now it displays N: (null) – Tony Eichelberger Sep 02 '09 at 21:21
-
NOOOOOO! I guess NSNumberFormatterBehavior10_0 is not available on the iphone SDK anymore? I was trying the example in a console app, but lo and behold that constant is not loger recognized for the iphone. – Tony Eichelberger Sep 02 '09 at 21:23
-
2This is a little old, but in case anybody is reading this, I thought it should be worth noting that an `NSScanner`, like `NSNumberFormatter`, takes locale into account when parsing the string, provided you use `setLocale:` on the scanner object (you could, for example, provide `[NSLocale currentLocale]`). – dreamlax Jan 07 '10 at 21:20
-
`NSNumberFormater`'s `numberFromString` is pretty straightForward. See my example below. – StuFF mc Nov 28 '11 at 20:42
-
1Some people read "War And Peace". Others prefer "Moby Dick". Myself, I think I am just going to pull down the Stack Overflow data set, filter out the questions with Dave's answers, and just enjoy. – BP. Mar 21 '12 at 14:18
-
`- (NSNumber *)numberFromString:` is not documented as returning `nil` on error. (See https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/Reference/Reference.html ). Can we rely upon this behaviour? – Mark Amery Aug 02 '13 at 12:25
-
1@MarkAmery Yes, you can rely on that behavior. Though it may not be documented, that is how it has behaved for many years, and changing it would be infeasible, from a binary compatibility point-of-view. – Dave DeLong Aug 02 '13 at 14:01
-
Can't we do something **like** *multiply the input by 1* or *subtract 0 from the input* and based on that see how it works? If it returns the same value for *1 then it should be a number or if it returns the same value when subtracted by 0. If its a string these operations would not work in a meaningful way–I think – mfaani Apr 21 '16 at 23:06
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]];
}
}

- 242,470
- 58
- 448
- 498

- 17,664
- 2
- 43
- 56
-
7Yes, this a horribly old answer, i know, but i thought static methods were declared like this: `+ (BOOL) TextIsValidValue:(NSString*)newText:(double)&value:`... – RCIX Jul 24 '11 at 20:49
-
7TextIsValidValue is a static C function, which means its local to the file and is not part of any object. You (@RCIX) are describing an object method, which is similar to a static method in C++ and is a completely different concept to a static C function (or a static variable for that matter!). – Peter N Lewis Aug 01 '11 at 03:47
-
-
Generally, for matching a number for input, you need to allow the empty string, otherwise the user cannot, for example, type "1
2". – Peter N Lewis Oct 10 '12 at 05:34 -
6For those developers that don't know what *regex* are or how they work, simply go to[this regex decoder wesbite](https://regex101.com/) and copy/paste `(?:|0|[1-9]\\d*)(?:\\.\\d*)` to see what it means. Also see [Regex Wikipedia](https://en.wikipedia.org/wiki/Regular_expression) – mfaani Apr 22 '16 at 00:43
-
regex101.com is very nice, but note that regex101.com says "Warning: An empty alternative effectively makes this group optional which suggests the alternative is completely redundant" which is entirely incorrect because of the ^ before - the alternatives specify either nothing, 0, or 1-9 followed by zero or more digits before the decimal point. It's certainly not optional, although you may prefer to disallow ".5" depending on your preference. – Peter N Lewis Apr 25 '16 at 06:37
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.

- 17,012
- 8
- 67
- 94
#pragma mark - UItextfield Delegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ([string isEqualToString:@"("]||[string isEqualToString:@")"]) {
return TRUE;
}
NSLog(@"Range ==%d ,%d",range.length,range.location);
//NSRange *CURRANGE = [NSString rangeOfString:string];
if (range.location == 0 && range.length == 0) {
if ([string isEqualToString:@"+"]) {
return TRUE;
}
}
return [self isNumeric:string];
}
-(BOOL)isNumeric:(NSString*)inputString{
BOOL isValid = NO;
NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:inputString];
isValid = [alphaNumbersSet isSupersetOfSet:stringSet];
return isValid;
}

- 16,511
- 11
- 49
- 56

- 1,775
- 19
- 33
Here are a few one-liners which combine Peter Lewis' answer above (Check that a input to UITextField is numeric only) with NSPredicates
#define REGEX_FOR_NUMBERS @"^([+-]?)(?:|0|[1-9]\\d*)(?:\\.\\d*)?$"
#define REGEX_FOR_INTEGERS @"^([+-]?)(?:|0|[1-9]\\d*)?$"
#define IS_A_NUMBER(string) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_NUMBERS] evaluateWithObject:string]
#define IS_AN_INTEGER(string) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_INTEGERS] evaluateWithObject:string]

- 1
- 1

- 393
- 4
- 12
For integer test it'll be:
- (BOOL) isIntegerNumber: (NSString*)input
{
return [input integerValue] != 0 || [input isEqualToString:@"0"];
}

- 1,772
- 1
- 21
- 27
-
Nice answer, but still the problem with this approach would be to have the input value '232asdfsadf', considered as Number. – Whoami Sep 08 '14 at 18:53
-
you could length compare the integerValue (re-convert to string) against original string to ensure "123aoenuthr" is not considered an integer. – ThePrimeagen Jul 31 '15 at 13:55
You can use the doubleValue of your string like
NSString *string=@"1.22";
double a=[string doubleValue];
i think this will return a as 0.0 if the string is invalid (it might throw an exception, in which case you can just catch it, the docs say 0.0 tho). more info here

- 22,706
- 18
- 63
- 99

- 22,363
- 9
- 64
- 71
-
Also, using a library function is usually better than rolling your own. In this case, other cultures use a comma for the decimal point, and presumably the Cocoa libs can handle that. – kibibu Aug 24 '09 at 03:38
-
not to mention doing literal float equality comparisons is just bad practice – M. Ryan Mar 14 '11 at 19:32
Hi had the exact same problem and I don't see the answer I used posted, so here it is.
I created and connected my text field via IB. When I connected it to my code via Control+Drag, I chose Action, then selected the Editing Changed event. This triggers the method on each character entry. You can use a different event to suit.
Afterwards, I used this simple code to replace the text. Note that I created my own character set to include the decimal/period character and numbers. Basically separates the string on the invalid characters, then rejoins them with empty string.
- (IBAction)myTextFieldEditingChangedMethod:(UITextField *)sender {
NSCharacterSet *validCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
NSCharacterSet *invalidCharacterSet = validCharacterSet.invertedSet;
sender.text = [[sender.text componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@""];
}
Credits: Remove all but numbers from NSString
Late to the game but here a handy little category I use that accounts for decimal places and the local symbol used for it. link to its gist here
@interface NSString (Extension)
- (BOOL) isAnEmail;
- (BOOL) isNumeric;
@end
@implementation NSString (Extension)
/**
* Determines if the current string is a valid email address.
*
* @return BOOL - True if the string is a valid email address.
*/
- (BOOL) isAnEmail
{
NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
return [emailTest evaluateWithObject:self];
}
/**
* Determines if the current NSString is numeric or not. It also accounts for the localised (Germany for example use "," instead of ".") decimal point and includes these as a valid number.
*
* @return BOOL - True if the string is numeric.
*/
- (BOOL) isNumeric
{
NSString *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator];
NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInString:localDecimalSymbol];
[decimalCharacterSet formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
NSCharacterSet* nonNumbers = [decimalCharacterSet invertedSet];
NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
if (r.location == NSNotFound)
{
// check to see how many times the decimal symbol appears in the string. It should only appear once for the number to be numeric.
int numberOfOccurances = [[self componentsSeparatedByString:localDecimalSymbol] count]-1;
return (numberOfOccurances > 1) ? NO : YES;
}
else return NO;
}
@end

- 5,096
- 4
- 36
- 54
-
shouldn't alphanumericCharacterSet be decimalDigitCharacterSet in isNumeric? this is how I use it. – Andrei Radulescu Aug 06 '14 at 12:44
-
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(string.length > 0)
{
NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:string];
BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
return stringIsValid;
}
return YES;
}

- 1,510
- 17
- 16
IMO the best way to accomplish your goal is to display a numeric keyboard rather than the normal keyboard. This restricts which keys are available to the user. This alleviates the need to do validation, and more importantly it prevents the user from making a mistake. The number pad is also much nicer for entering numbers because the keys are substantially larger.
In interface builder select the UITextField, go to the Attributes Inspector and change the "Keyboard Type" to "Decimal Pad".
That'll make the keyboard look like this:
The only thing left to do is ensure the user doesn't enter in two decimal places. You can do this while they're editing. Add the following code to your view controller. This code removes a second decimal place as soon as it is entered. It appears to the user as if the 2nd decimal never appeared in the first place.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.textField addTarget:self
action:@selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];
}
- (void)textFieldDidChange:(UITextField *)textField
{
NSString *text = textField.text;
NSRange range = [text rangeOfString:@"."];
if (range.location != NSNotFound &&
[text hasSuffix:@"."] &&
range.location != (text.length - 1))
{
// There's more than one decimal
textField.text = [text substringToIndex:text.length - 1];
}
}

- 2,429
- 24
- 15
-
1
-
1This does not address all cases. A user could copy paste text or use a bluetooth keyboard. – bean Dec 12 '16 at 23:43
Old thread, but it's worth mentioning that Apple introduced NSRegularExpression
in iOS 4.0. (Taking the regular expression from Peter's response)
// Look for 0-n digits from start to finish
NSRegularExpression *noFunnyStuff = [NSRegularExpression regularExpressionWithPattern:@"^(?:|0|[1-9]\\d*)(?:\\.\\d*)?$" options:0 error:nil];
// There should be just one match
if ([noFunnyStuff numberOfMatchesInString:<#theString#> options:0 range:NSMakeRange(0, <#theString#>.length)] == 1)
{
// Yay, digits!
}
I suggest storing the NSRegularExpression
instance somewhere.

- 8,502
- 48
- 57
@property (strong) NSNumberFormatter *numberFormatter;
@property (strong) NSString *oldStringValue;
- (void)awakeFromNib
{
[super awakeFromNib];
self.numberFormatter = [[NSNumberFormatter alloc] init];
self.oldStringValue = self.stringValue;
[self setDelegate:self];
}
- (void)controlTextDidChange:(NSNotification *)obj
{
NSNumber *number = [self.numberFormatter numberFromString:self.stringValue];
if (number) {
self.oldStringValue = self.stringValue;
} else {
self.stringValue = self.oldStringValue;
}
}

- 4,137
- 2
- 33
- 32
Not so elegant, but simple :)
- (BOOL) isNumber: (NSString*)input
{
return [input doubleValue] != 0 || [input isEqualToString:@"0"] || [input isEqualToString:@"0.0"];
}

- 1,772
- 1
- 21
- 27
-
1This solution doesn't work with infinite zeros like 0.00. So I won't suggest people using it – Vinh Sep 14 '14 at 16:50
Accept decimal values in text fields with single (.)dot working with iPad and iPhone in Swift 3
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let inverseSet = NSCharacterSet(charactersIn:"0123456789").inverted
let components = string.components(separatedBy: inverseSet)
let filtered = components.joined(separator: "")
if filtered == string {
return true
} else {
if string == "." {
let countdots = textField.text!.components(separatedBy:".").count - 1
if countdots == 0 {
return true
}else{
if countdots > 0 && string == "." {
return false
} else {
return true
}
}
}else{
return false
}
}
}

- 2,669
- 2
- 30
- 37
I wanted a text field that only allowed integers. Here's what I ended up with (using info from here and elsewhere):
Create integer number formatter (in UIApplicationDelegate so it can be reused):
@property (nonatomic, retain) NSNumberFormatter *integerNumberFormatter;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create and configure an NSNumberFormatter for integers
integerNumberFormatter = [[NSNumberFormatter alloc] init];
[integerNumberFormatter setMaximumFractionDigits:0];
return YES;
}
Use filter in UITextFieldDelegate:
@interface MyTableViewController : UITableViewController <UITextFieldDelegate> {
ictAppDelegate *appDelegate;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Make sure the proposed string is a number
NSNumberFormatter *inf = [appDelegate integerNumberFormatter];
NSString* proposedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSNumber *proposedNumber = [inf numberFromString:proposedString];
if (proposedNumber) {
// Make sure the proposed number is an integer
NSString *integerString = [inf stringFromNumber:proposedNumber];
if ([integerString isEqualToString:proposedString]) {
// proposed string is an integer
return YES;
}
}
// Warn the user we're rejecting the change
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
return NO;
}

- 4,013
- 3
- 27
- 33
This answer uses NSFormatter as said previously. Check it out:
@interface NSString (NSNumber)
- (BOOL) isNumberWithLocale:(NSLocale *) stringLocale;
- (BOOL) isNumber;
- (NSNumber *) getNumber;
- (NSNumber *) getNumberWithLocale:(NSLocale*) stringLocale;
@end
@implementation NSString (NSNumber)
- (BOOL) isNumberWithLocale:(NSLocale *) stringLocale
{
return [self getNumberWithLocale:stringLocale] != nil;
}
- (BOOL) isNumber
{
return [ self getNumber ] != nil;
}
- (NSNumber *) getNumber
{
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: @"en_US"] ;
return [self getNumberWithLocale: [l_en autorelease] ];
}
- (NSNumber *) getNumberWithLocale:(NSLocale*) stringLocale
{
NSNumberFormatter *formatter = [[ [ NSNumberFormatter alloc ] init ] autorelease];
[formatter setLocale: stringLocale ];
return [ formatter numberFromString:self ];
}
@end
I hope it helps someone. =)

- 22,706
- 18
- 63
- 99

- 1,076
- 12
- 21
To be more international (and not only US colored ;-) ) just replace in the code above by
-(NSNumber *) getNumber
{
NSString* localeIdentifier = [[NSLocale autoupdatingCurrentLocale] localeIdentifier];
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: localeIdentifier] ;
return [self getNumberWithLocale: [l_en autorelease] ];
}

- 22,706
- 18
- 63
- 99

- 181
- 1
- 6
#import "NSString+Extension.h"
//@interface NSString (Extension)
//
//- (BOOL) isAnEmail;
//- (BOOL) isNumeric;
//
//@end
@implementation NSString (Extension)
- (BOOL) isNumeric
{
NSString *emailRegex = @"[0-9]+";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
return [emailTest evaluateWithObject:self];
// NSString *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator];
// NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInString:localDecimalSymbol];
// [decimalCharacterSet formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
//
// NSCharacterSet* nonNumbers = [decimalCharacterSet invertedSet];
// NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
//
// if (r.location == NSNotFound)
// {
// // check to see how many times the decimal symbol appears in the string. It should only appear once for the number to be numeric.
// int numberOfOccurances = [[self componentsSeparatedByString:localDecimalSymbol] count]-1;
// return (numberOfOccurances > 1) ? NO : YES;
// }
// else return NO;
}

- 4,507
- 4
- 49
- 45
In Swift 4:
let formatString = "12345"
if let number = Decimal(string:formatString){
print("String contains only number")
}
else{
print("String doesn't contains only number")
}

- 2,651
- 1
- 24
- 21
This covers: Decimal part control (including number of decimals allowed), copy/paste control, international separators.
Steps:
Make sure your view controller inherits from UITextFieldDelegate
class MyViewController: UIViewController, UITextFieldDelegate {...
In viewDidLoad, set your control delegate to self:
override func viewDidLoad() { super.viewDidLoad(); yourTextField.delegate = self }
Implement the following method and update the "decsAllowed" constant with the desired amount of decimals or 0 if you want a natural number.
Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let decsAllowed: Int = 2
let candidateText = NSString(string: textField.text!).replacingCharacters(in: range, with: string)
let decSeparator: String = NumberFormatter().decimalSeparator!;
let splitted = candidateText.components(separatedBy: decSeparator)
let decSeparatorsFound = splitted.count - 1
let decimalPart = decSeparatorsFound > 0 ? splitted.last! : ""
let decimalPartCount = decimalPart.characters.count
let characterSet = NSMutableCharacterSet.decimalDigit()
if decsAllowed > 0 {characterSet.addCharacters(in: decSeparator)}
let valid = characterSet.isSuperset(of: CharacterSet(charactersIn: candidateText)) &&
decSeparatorsFound <= 1 &&
decsAllowed >= decimalPartCount
return valid
}
If afterwards you need to safely convert that string into a number, you can just use Double(yourstring) or Int(yourstring) type cast, or the more academic way:
let formatter = NumberFormatter()
let theNumber: NSNumber = formatter.number(from: yourTextField.text)!

- 657
- 1
- 7
- 8