30

I have UITexfields i want that it should accept only number other shows alert that enter a numeric value. I want that motionSicknessTextFiled should only accept number

NSString*dogswithMotionSickness=motionSicknessTextField.text;
NSString*valueOne=cereniaTextField.text;
NSString*valueTwo=prescriptionTextField.text;
NSString*valueThree=otherMeansTextField.text;
NSString*valueFour=overtheCounterTextField.text;
Karthik Kumar
  • 1,165
  • 1
  • 9
  • 29
james
  • 626
  • 3
  • 9
  • 23

14 Answers14

58

In whatever UITextField you're getting these values from, you can specify the kind of keyboard you want to appear when somebody touches inside the text field.

E.G. a numeric-only keyboard.

Like this screenshot:

numeric only keyboard will appear

This is easily set when working with the XIB and the Interface Builder built into Xcode, but if you want to understand this programmatically, take a look at Apple's UITextInputTraits protocol reference page, specifically the keyboardType property information.

To filter out punctuations, set the textfield's delegate and set up the shouldChangeCharactersInRange method:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
    NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:textField.text];

    BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
    return stringIsValid;
}
kalpesh satasiya
  • 797
  • 8
  • 18
Michael Dautermann
  • 86,557
  • 17
  • 155
  • 196
  • 2
    Also on a side note to take decimal inputs (float) use the DecimalPad. – Munim Dibosh Jun 21 '14 at 18:25
  • 5
    You should use `[textField.text stringByReplacingCharactersInRange:range withString:string]` and not `textField.text` when creating `characterSetFromTextField` as the `text` property has not updated yet. – liamnichols May 27 '15 at 16:25
  • In xcode 7, you may find this option in the attributes inspector tab. There is an option called keyboard types. – toing_toing Jul 18 '16 at 17:21
  • This code is allowing the first character as alphabetic. how to fix that? – R. Mohan Dec 02 '18 at 06:51
  • @R.Mohan did you set the keyboard type to numeric? make sure you return ‘false’ from that method for any alphabetic characters. – Michael Dautermann Dec 02 '18 at 07:21
  • @MichaelDautermann I set the keyboard type to Phone Pad, stringIsValid is returning YES for the first alphabetic character and NO for second or third alphabets. – R. Mohan Dec 02 '18 at 08:57
26

Objective C

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

    if (textField == self.tmpTextField)
    {
        NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
        NSString *expression = @"^([0-9]+)?(\\.([0-9]{1,2})?)?$";
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression 
                                                                               options:NSRegularExpressionCaseInsensitive 
                                                                                 error:nil];
        NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString
                                                            options:0
                                                              range:NSMakeRange(0, [newString length])];        
        if (numberOfMatches == 0)
            return NO;        
    }
    return YES;
}

Swift 3.0

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if !string.characters.count {
        return true
    }
    do {
        if textField == self.tmpTextField {
            var newString = textField.text.replacingCharacters(inRange: range, with: string)
            var expression = "^([0-9]+)?(\\.([0-9]{1,2})?)?$"
            var regex = try NSRegularExpression(pattern: expression, options: NSRegularExpressionCaseInsensitive)
            var numberOfMatches = regex.numberOfMatches(inString: newString, options: [], range: NSRange(location: 0, length: newString.characters.count))
            if numberOfMatches == 0 {
                return false
            }
        }
    }
    catch let error {
    }
    return true
}
Himanshu padia
  • 6,141
  • 1
  • 41
  • 44
  • This doesn't allow you to delete characters once you are done editing. – Rahul Sharma May 19 '14 at 16:47
  • 5
    @RahulSharma In this example, you can allow deletion of characters by placing a check on the length of the `string` argument and returning `YES` if the string is empty. Something like `if (!string.length) return YES;` – Beltalowda May 28 '14 at 16:27
10
[textField setKeyboardType:UIKeyboardTypeNumberPad];
Martol1ni
  • 4,616
  • 2
  • 27
  • 38
10

I've implemented the snippet which has the features for textField:

  1. Check the maximum allowed characters.
  2. Check the valid decimal number.
  3. Check only numeric numbers.

The code is the UITextField delegate method. Before you use this snippet, you must have these properties:

  1. self.maxCharacters
  2. self.numeric // Only int characters.
  3. self.decimalNumeric // Only numbers and ".", "," (for specific locales, like Russian).

Code:

- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if(self.numeric || self.decimalNumeric)
    {
        NSString *fulltext = [textField.text stringByAppendingString:string];
        NSString *charactersSetString = @"0123456789";

        // For decimal keyboard, allow "dot" and "comma" characters.
        if(self.decimalNumeric) {
            charactersSetString = [charactersSetString stringByAppendingString:@".,"];
        }

        NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:charactersSetString];
        NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:fulltext];

        // If typed character is out of Set, ignore it.
        BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
        if(!stringIsValid) {
            return NO;
        }

        if(self.decimalNumeric)
        {
            NSString *currentText = [textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

            // Change the "," (appears in other locale keyboards, such as russian) key ot "."
            currentText = [currentText stringByReplacingOccurrencesOfString:@"," withString:@"."];

            // Check the statements of decimal value.
            if([fulltext isEqualToString:@"."]) {
                textField.text = @"0.";
                return NO;
            }

            if([fulltext rangeOfString:@".."].location != NSNotFound) {
                textField.text = [fulltext stringByReplacingOccurrencesOfString:@".." withString:@"."];
                return NO;
            }

            // If second dot is typed, ignore it.
            NSArray *dots = [fulltext componentsSeparatedByString:@"."];
            if(dots.count > 2) {
                textField.text = currentText;
                return NO;
            }

            // If first character is zero and second character is > 0, replace first with second. 05 => 5;
            if(fulltext.length == 2) {
                if([[fulltext substringToIndex:1] isEqualToString:@"0"] && ![fulltext isEqualToString:@"0."]) {
                    textField.text = [fulltext substringWithRange:NSMakeRange(1, 1)];
                    return NO;
                }
            }
        }
    }

    // Check the max characters typed.
    NSUInteger oldLength = [textField.text length];
    NSUInteger replacementLength = [string length];
    NSUInteger rangeLength = range.length;

    NSUInteger newLength = oldLength - rangeLength + replacementLength;
    BOOL returnKey = [string rangeOfString: @"\n"].location != NSNotFound;

    return newLength <= _maxCharacters || returnKey;
}

Demo:

enter image description here

Almas Adilbek
  • 4,171
  • 10
  • 55
  • 94
7

Modified Michael Dautermann's answer:

- (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;
}
Hsm
  • 1,430
  • 15
  • 16
3

swift 4

This allows only number input and you can also set character limitation

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
  let aSet = NSCharacterSet(charactersIn:"0123456789").inverted
  let compSepByCharInSet = string.components(separatedBy: aSet)
  let numberFiltered = compSepByCharInSet.joined(separator: "")

  if string == numberFiltered {
    let currentText = textField.text ?? ""
    guard let stringRange = Range(range, in: currentText) else { return false }
    let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
    return updatedText.count <= 10
  } else {
    return false
  }
}
budiDino
  • 10,932
  • 8
  • 84
  • 83
ravi alagiya
  • 190
  • 2
  • 8
2

Here is Swift solution:

In viewDidLoad set the delegate:

_yourTextField.delegate = self
let _acceptableCharacters = "0123456789."

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

    if (string.characters.count == 0) {
        return true
    }

    if (textField == self._yourTextField) {
        let cs = NSCharacterSet(charactersInString: self._acceptableCharacters)
        let filtered = string.componentsSeparatedByCharactersInSet(cs).filter {  !$0.isEmpty }
        let str = filtered.joinWithSeparator("")

        return (string != str)
    }

    return true
}
pchelnikov
  • 281
  • 3
  • 6
1

this is the function which checks for the String contains Numeric value only

+(BOOL) checkforNumeric:(NSString*) str
{
    NSString *strMatchstring=@"\\b([0-9%_.+\\-]+)\\b"; 
    NSPredicate *textpredicate=[NSPredicate predicateWithFormat:@"SELF MATCHES %@", strMatchstring];

    if(![textpredicate evaluateWithObject:str])
    {
        //////NSLog(@"Invalid email address found");
        UIAlertView *objAlert = [[UIAlertView alloc] initWithTitle:APP_NAME message:@"please enter valid text." delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Close",nil];
        [objAlert show];
        [objAlert release];
        return FALSE;
    }
    return TRUE;
}

check it on submit button.

Prabhat Kasera
  • 1,111
  • 11
  • 28
1

This answer threw some error in Swift 3, here's the working answer:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if string.characters.count == 0 {
        return true
    }
    do {
        if textField == self.numberTextField {

            let nString = textField.text as NSString?
            let newString = nString?.replacingCharacters(in: range, with: string)
            let expression = "^([0-9]+)?(\\.([0-9]{1,2})?)?$"
            let regex = try NSRegularExpression(pattern: expression, options: .caseInsensitive)
            let numberOfMatches = regex.numberOfMatches(in: newString! as String, options: [], range: NSRange(location: 0, length: (newString?.characters.count)!))

            if numberOfMatches == 0 {
                return false
            }
        }
    }
    catch let error {
    }
    return true
}
Arpit Dongre
  • 1,665
  • 16
  • 28
0

I just modified the answer of Michael and made it a little bit easier to implement. Just make sure that the delegate of your UITextfield is set to itself.

yourTxtField.delegate = self;

Furthermore copy & paste this code into your main file.

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

    if (textField == yourTxtField) {
        NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
        NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:string];

        BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
            return stringIsValid;
        }else {
            return YES;
        }
    }

If you want to allow the use of the spacebar just put in a blank space at the end of the CharactersInString, just like so:

@"0123456789" -> @"0123456789 "

Additionally:

If you want to restrict the length of the string just replace the if-function with following:

if (textField == yourTxtField) {
        NSUInteger newLength = [textField.text length] + [string length] - range.length;
        NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"1234567890"] invertedSet];
        NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
        return (([string isEqualToString:filtered])&&(newLength <= 10));

    }

In my case the "10" at the end represents the limit of characters.

Cheers! :)

MasterRazer
  • 1,367
  • 3
  • 16
  • 40
0

Swift 4.2 port of the best answer here by @almas-adlibek

A bunch of configuration variables:

private let kMaxTextLength = 8
private let kZeroDotted = "0."
private let kZero = "0"
private let kDoubleDot = ".."
private let kDot = "."
private let kPeriod = ","

Now the Swift 4 converted part of the code.

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

    guard let oldText = textField.text, let swiftRange = Range(range, in: oldText) else {
        return true
    }

    let newText = oldText.replacingCharacters(in: swiftRange, with: string)

    var currentText =  textField.text?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)

    // Change the "," (appears in other locale keyboards, such as russian) key ot "."
    currentText = currentText?.replacingOccurrences(of: kPeriod, with: kDot)

    // Check the statements of decimal value.
    if (newText == kDot) {
        textField.text = kZeroDotted;
        return false
    }

    if (newText.range(of: kDoubleDot) != nil) {
        textField.text = newText.replacingOccurrences(of: kDoubleDot, with: kDot);
        return false
    }

    // If second dot is typed, ignore it.
    let dots = newText.components(separatedBy: kDot)
    if(dots.count > 2) {
        textField.text = currentText;
        return false
    }

    // If first character is zero and second character is > 0, replace first with second. 05 => 5;
    if(newText.count == 2) {
        if(newText[0...0] == kZero && newText != kZeroDotted) {
            textField.text = newText[1...1]
            return false
        }
    }

    // Check the max characters typed.
    let oldLength = textField.text?.count ?? 0
    let replacementLength = string.count
    let rangeLength = range.length

    let newLength = oldLength - rangeLength + replacementLength;
    let returnKey = string.rangeOfCharacter(from: CharacterSet.newlines) != nil

    return newLength <= kMaxTextLength || returnKey;
}
Michael
  • 1,097
  • 14
  • 31
-1

Swift

class ExampleVC: UIViewController {

    let numbers = "0123456789";

    override func viewDidLoad() {
        super.viewDidLoad()

        let textfield = UITextField(frame: CGRectMake(20, 100, 300, 44))
        //make some customization, if you want
        self.view.addSubview(textfield)

        textfield.delegate = self;
    }
}

extension ExampleVC: UITextFieldDelegate {

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return string.characters.count > 0 ? numbers.contains(string) : true
    }
}
tier777
  • 915
  • 11
  • 11
-1

Another option of entering only numeric values into your text field is by selecting the keyboard type attribute of the corresponding textfield. Attaching the screenshot for reference.Number Pad Selection

Haseeb Mohamed
  • 1,351
  • 1
  • 8
  • 15
  • can u share code for textfield with icon you are using. – Syed Faraz Haider Zaidi Jan 21 '19 at 09:11
  • On iPad the number pad just defaults to the normal keyboard with shift selected. The user can still shift back to alphabetic. Furthermore the user can copy-and-paste any text on any device. – Dale May 14 '19 at 00:08
-2

Here is the working example for swift 4

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
    // Allow Backspace
    if string.count == 0 {
        return true
    }

    // Allow Only Valid Decimal Numbers
    if let textFieldText = textField.text   {

        let finalText = (textFieldText as NSString).replacingCharacters(in: range, with: string)
        if Double(finalText) != nil {
            return true
        }
    }
    return false
}