94

I want the user to only enter numeric values in a UITextField. On iPhone we can show the numeric keyboard, but on iPad the user can switch to any keyboard.

Is there any way to restrict user to enter only numeric values in a UITextField?


Note: This is an old question with many many answers. More than one third of the posted answers are wrong. Even some of the highly upvoted answers are wrong. Please, DO NOT post a new answer unless it somehow finds a vastly improved way to solve this question in a way that isn't shown already. Make sure your answer works in all circumstances. It must work for both iPhones and iPads. It must work when a user pastes text into the text field. It must work if the user has an external keyboard. It must work if the user changes the text selection in the text field before typing or pasting text. It must properly support decimal numbers (one decimal separator appropriate for the user's locale).

HangarRash
  • 7,314
  • 5
  • 5
  • 32

37 Answers37

109

Solution for swift 3.0 and above

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let allowedCharacters = CharacterSet.decimalDigits
    let characterSet = CharacterSet(charactersIn: string)
    return allowedCharacters.isSuperset(of: characterSet)
}
אורי orihpt
  • 2,358
  • 2
  • 16
  • 41
Hiren Panchal
  • 2,963
  • 1
  • 25
  • 21
82

Here is my 2 Cents. (Tested on Swift 2 Only)

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

  let aSet = NSCharacterSet(charactersInString:"0123456789").invertedSet
  let compSepByCharInSet = string.componentsSeparatedByCharactersInSet(aSet)
  let numberFiltered = compSepByCharInSet.joinWithSeparator("")
  return string == numberFiltered

}

This is just a little bit more strict. No decimal point either.

Hope it helps :)

PS: I assumed you looked after the delegate anyway.

Update: Swift 3.0 :

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: "")
    return string == numberFiltered
}
Aawara
  • 301
  • 3
  • 18
Mr H
  • 5,254
  • 3
  • 38
  • 43
33

In swift 4.1 and Xcode 9.4.1

Add UITextFieldDelegate to your class

class YourViewController: UIViewController, UITextFieldDelegate

Then write this code in your viewDidLoad()

mobileNoTF.delegate = self

Write this textfield delegate function

//MARK - UITextField Delegates
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    //For mobile numer validation
    if textField == mobileNoTF {
        let allowedCharacters = CharacterSet(charactersIn:"+0123456789 ")//Here change this characters based on your requirement
        let characterSet = CharacterSet(charactersIn: string)
        return allowedCharacters.isSuperset(of: characterSet)
    }
    return true
}
Naresh
  • 16,698
  • 6
  • 112
  • 113
  • how do i fix `Binary operator '==' cannot be applied to operands of type 'UITextField' and '() -> ()'` – newswiftcoder Feb 21 '20 at 11:49
  • @iOS, how does it works? I've added everything, but I still can type anything. The field allows any characters and the textField function is not triggered. – Smit Apr 23 '20 at 12:20
16

iPhone

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:

enter image description here

iPad

The iPad does not support the numeric keyboard, so your options are to either not support the iPad, validate the field post submit, or follow one of the other suggestions here to create same behaviors while running on an iPad.

Jamil Hasnine Tamim
  • 4,389
  • 27
  • 43
  • 19
    This doesn't answer the question. Even when using the Number Pad, iOS would allow a user to paste non-numeric values into the UITextField or allow iPads to switch keyboards away from numeric. – Rob Feb 05 '18 at 22:05
  • This is simple answer of this question!! Not proper answer! I know! – Jamil Hasnine Tamim Feb 06 '18 at 05:58
  • 2
    It's not any answer to the question, neither simple nor proper. The question **isn't** asking for how to change the keyboard type. The question **is** asking how to restrict the input. Those are different. – Rob Feb 07 '18 at 22:31
  • Question is: How to restrict UITextField to take only numbers in Swift? So when your keyboard type is number pad, obviously it's fulfill the requirements. – Jamil Hasnine Tamim Feb 08 '18 at 04:24
  • No, it doesn't, because the preferred keyboard type that you set on the UITextField is *not* the only way to enter text into a text field. As Rob said, you can also paste text into it, you can use an external keyboard, and some devices let you switch to a different keyboard type in any case. – Andrew M Feb 13 '18 at 23:45
  • 1
    The OP asks explicitly for another solution than changing keyboard type. "On iPhone we can show the numeric keyboard, but on iPad the user can switch to any keyboard." – Ferdz Apr 23 '18 at 14:53
  • Actually this also doesn't answer for iPhone. If the user has a custom keyboard, you can bypass the numberPad only configuration. – NSPunk Nov 07 '21 at 11:07
14

Swift 2.0

For only allowing numbers and one "." decimal in uitextfield.

func textField(textField: UITextField,shouldChangeCharactersInRange range: NSRange,replacementString string: String) -> Bool
{
    let newCharacters = NSCharacterSet(charactersInString: string)
    let boolIsNumber = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newCharacters)
    if boolIsNumber == true {
        return true
    } else {
        if string == "." {
            let countdots = textField.text!.componentsSeparatedByString(".").count - 1
            if countdots == 0 {
                return true
            } else {
                if countdots > 0 && string == "." {
                    return false
                } else {
                    return true
                }
            }
        } else {
            return false
        }
    }
}
derdida
  • 14,784
  • 16
  • 90
  • 139
Cian
  • 263
  • 4
  • 8
9

Accept decimal values in text fields with single (.)dot 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
        }
    }
}
Raj Joshi
  • 2,669
  • 2
  • 30
  • 37
7
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    // return true if the replacementString only contains numeric characters
    let digits = NSCharacterSet.decimalDigitCharacterSet()
    for c in string {
        if !digits.characterIsMember(c) {
            return false
        }
    }

    return true
}

This solution will work even if the user switches keyboards or tries to paste a non-numeric string into the text field.

Make sure to set the delegate property of the appropriate text field.

ndmeiri
  • 4,979
  • 12
  • 37
  • 45
  • 1
    Using `[string intValue]` as suggested in a previous answer will not work because that property could be true (non-zero) even if `string` contains non-numeric characters. According to the docs, `intValue` is 0 only if "the string doesn’t begin with a valid decimal text representation of a number." – ndmeiri Jun 22 '15 at 06:43
7

Extend your view controller like this:

class MyViewController: UIViewController, UITextFieldDelegate

In the viewDidLoad function extend to your text field like this:

myTextField.delegate = self

And then use the following function:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let isNumber = CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string))
    let withDecimal = (
        string == NumberFormatter().decimalSeparator &&
        textField.text?.contains(string) == false
    )
    return isNumber || withDecimal
}

This will now make sure the user can enter only decimal digits.

Swift 4 + Accepts Number only and accepts one separator

zeeshan
  • 4,913
  • 1
  • 49
  • 58
Aftab Ahmed
  • 99
  • 1
  • 8
5

Use number formatter

Swift 4.x

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
      let s = NSString(string: textField.text ?? "").replacingCharacters(in: range, with: string)
      guard !s.isEmpty else { return true }
      let numberFormatter = NumberFormatter()
      numberFormatter.numberStyle = .none
      return numberFormatter.number(from: s)?.intValue != nil
 }
SPatel
  • 4,768
  • 4
  • 32
  • 51
4

Here is a simple solution, you need to connect the event "Editing changed" to this method in your controller

Swift 4

@IBAction func valueChanged(_ sender: UITextField) {
    if let last = sender.text?.last {
        let zero: Character = "0"
        let num: Int = Int(UnicodeScalar(String(last))!.value - UnicodeScalar(String(zero))!.value)
        if (num < 0 || num > 9) {
            //remove the last character as it is invalid
            sender.text?.removeLast()
        }
    }
}
shbli
  • 566
  • 1
  • 6
  • 14
4

1st you have to inherit the UITextFieldDelegate class with you own class

class ViewController: UIViewController, UITextFieldDelegate {

2nd add an IBOutlet

@IBOutlet weak var firstName: UITextField!

3rd you have to assure this object is using

override func viewDidLoad() {
        super.viewDidLoad()
   firstName.delegate = self
}


func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if textField == firstName {
                let allowedCharacters = "1234567890"
                let allowedCharacterSet = CharacterSet(charactersIn: allowedCharacters)
                let typedCharacterSet = CharacterSet(charactersIn: string)
                let alphabet = allowedCharacterSet.isSuperset(of: typedCharacterSet)
                return alphabet


      }
  }
Akbar Khan
  • 2,215
  • 19
  • 27
  • Why would you name a text field for entering numbers as `firstName`? An outlet is not needed if the text field is created programmatically. – HangarRash Mar 17 '23 at 20:27
3

Tested in swift 3.0

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

{         
    let numberOnly = NSCharacterSet.init(charactersIn: "0123456789")
    let stringFromTextField = NSCharacterSet.init(charactersIn: string)
    let strValid = numberOnly.isSuperset(of: stringFromTextField as CharacterSet)

     return strValid
 }
Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92
iosLearner
  • 1,312
  • 1
  • 16
  • 30
3

While most of these solutions will work, be aware that in some localisations a decimals are separated with a "," and not a "."

The cleaner way to do this would be

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let decimalCharacter = NSNumberFormatter().decimalSeparator
    let characterSet = NSMutableCharacterSet.decimalDigitCharacterSet()
    characterSet.addCharactersInString(decimalCharacter)

    return replacementString.rangeOfCharacterFromSet(characterSet.invertedSet) == nil
}
2

I had actually done this when working through the Big Nerd Ranch book, my solution is:

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

    let newCharacters = NSCharacterSet(charactersInString: string)
    return NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newCharacters)
}

this only allows the numbers 0-9, to allow the "." as well is more complicated as you can only allow one "."

sgib
  • 1,030
  • 11
  • 7
2
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if let numRange = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet()) {
        return false
    } else {
        return true
    }
   }
likarson
  • 95
  • 1
  • 2
2

To allow only numbers and just one decimal operator, you can use this solution:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let isNumber = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(NSCharacterSet(charactersInString: string))

    return isNumber || (string == NSNumberFormatter().decimalSeparator && textField.text?.containsString(string) == false)
}
hprione
  • 21
  • 3
2
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool

        {
            let textString = (textField.text! as NSString).replacingCharacters(in: range, with: string)

            if textField == self.phoneTextField  && string.characters.count > 0{
                let numberOnly = NSCharacterSet.decimalDigits
                let strValid = numberOnly.contains(UnicodeScalar.init(string)!)
                return strValid && textString.characters.count <= 10
            }
            return true
        }

in above code is working in swift 3
NSCharacterSet.decimalDigits
You are also use letters only
NSCharacterSet.Letters
and uppercase,Lowercaseand,alphanumerics,whitespaces is used same code or See the Link

Ramprasath Selvam
  • 3,868
  • 3
  • 25
  • 41
2

Here's an cleaner solution:

 guard CharacterSet(charactersIn: "123456789").isSuperset(of: CharacterSet(charactersIn: string)) else {
     return false
 }
 return true

For decimals just add ., example 123456789.

Brian Nezhad
  • 6,148
  • 9
  • 44
  • 69
2

Set KeyboardType Property :- Number Pad TextField Delegate please write below code

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

    if textField.text?.count == 0 && string == "0" {
        return false
    }
    return string == string.filter("0123456789".contains)
}

Number should not start from 0 and entered number +ve.

Jagadeesh K
  • 121
  • 2
  • 9
  • Never rely on the keyboard type. A user can still paste in arbitrary text or an external keyboard could be used. And please read the question about the iPad. Why does this answer prevent a user from entering a `0` into an empty text field? – HangarRash Mar 17 '23 at 20:29
2

//instead of these you can simply change your keyboard to number type

yourtextfield.keyboardType = UIKeyboardType.numberPad
keshav
  • 96
  • 7
1
Swift 2.0

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

        let inverseSet = NSCharacterSet(charactersInString:"0123456789").invertedSet

        let components = string.componentsSeparatedByCharactersInSet(inverseSet)

        let filtered = components.joinWithSeparator("")

        return string == filtered

  }
Edison
  • 11,881
  • 5
  • 42
  • 50
1

As if there aren't enough answers, here's mine. I think every example allowed for decimal separators is flawed in either localization, backspaces, or copy/paste.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string.isEmpty {return true} //allow for backspace

    let decimalSeparator = NSNumberFormatter().decimalSeparator ?? "."
    let validChars = NSMutableCharacterSet(charactersInString: decimalSeparator)
    validChars.formUnionWithCharacterSet(NSCharacterSet.decimalDigitCharacterSet())

    if validChars.isSupersetOfSet(NSCharacterSet(charactersInString: string)){
        switch string.componentsSeparatedByString(decimalSeparator).count-1 {
        case 0: //no decimals
            return true

        case 1: //if adding decimal, only allow if no existing decimal
            if let existingText = textField.text{
                return existingText.componentsSeparatedByString(decimalSeparator).count <= 1
            }
            else {return true}

        default: //invalid decimals
            return false
        }
    }

    return false
}
David
  • 95
  • 1
  • 7
1
func isValidNumber(str:String) -> Bool{
    if str.isEmpty {
        return false
    }
    let newChar = NSCharacterSet(charactersInString: str)
    let boolValid = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newChar)
    if boolValid{
        return true
    }else{
        let lst = str.componentsSeparatedByString(".")
        let newStr = lst.joinWithSeparator("")
        let currentChar = NSCharacterSet(charactersInString: newStr)
        if lst.count == 2 && !lst.contains("") && NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(currentChar){
            return true
        }
        return false
    }
}

Put this function in your "Submit" or "Save" method if there is one.

den330
  • 387
  • 1
  • 3
  • 15
1

The following is the code I used in Swift 3.0 adapted from Mr H's code. Differences are because:

a) Delegate function declaration has changed in Swift 3.0. New declaration here

b) NSCharacterSet declaration has changed.

func textField(_ shouldChangeCharactersIntextField: 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: "")

        return string == filtered

}
ChinLoong
  • 1,735
  • 24
  • 26
1

I have edited Raj Joshi's version to allow one dot or one comma:

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

    let inverseSet = CharacterSet(charactersIn:"0123456789").inverted
    let components = string.components(separatedBy: inverseSet)
    let filtered = components.joined(separator: "")

    if filtered == string {
        return true
    } else {
        if string == "." || string == "," {
            let countDots = textField.text!.components(separatedBy:".").count - 1
            let countCommas = textField.text!.components(separatedBy:",").count - 1

            if countDots == 0 && countCommas == 0 {
                return true
            } else {
                return false
            }
        } else  {
            return false
        }
    }
}
Matthijs
  • 515
  • 4
  • 8
  • This fails under some conditions. This doesn't take into account the possibility of the user selecting some text before typing or pasting text. – HangarRash Mar 17 '23 at 20:39
1

You can use this code if you want to allow decimal separator and/or negative numbers. But this code allows example: "34." (decimal separator at the end) while changing text. So you have to add some code example: textFieldShouldReturn or textFieldShouldEndEditing delegate functions.

The code written in Swift 4 but I assueme this is compatible with Swift 3.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let text = textField.text else {
        return true
    }

    let replaced = (text as NSString).replacingCharacters(in: range, with: string)
    let decimalSeparator = NSLocale.current.decimalSeparator ?? ""

    // When user wants to delete las character
    if replaced == "" || replaced == "-" || replaced == "-0" {
        textField.text = "0"
        return false
    }

    // When text contains 0 before replace except "0."
    if replaced != "0" + decimalSeparator && replaced.hasPrefix("0") && text.underestimatedCount == 1 {
        textField.text = replaced.substring(from: replaced.index(after: replaced.startIndex))
        return false
    }

    // When user wants to delete minus sign
    if text.hasPrefix("-") && text.substring(from: text.index(after: text.startIndex)) == replaced {
        return false
    }

    // When user wants to delete before decimal separator
    if replaced.hasPrefix(decimalSeparator) || replaced.hasPrefix("-" + decimalSeparator) {
        return false
    }

    // When user wants to add zero the beginning of number... but allowing "0." or "-0." numbers
    let testReplaced = replaced.hasPrefix("-") ? replaced.substring(from: replaced.index(after: replaced.startIndex)) : replaced
    if testReplaced.count >= 2 && testReplaced.hasPrefix("0") && !testReplaced.hasPrefix("0" + decimalSeparator) {
        return false
    }

    // Every other cases
    let allowDecimal = self.allowFloat ? (decimalSeparator == "." ? "\\.?" : decimalSeparator + "?") : ""
    let allowSign = self.allowSigned ? "-?" : ""
    let pattern = "\(allowSign)[0-9]+\(allowDecimal)([0-9]+)?"

    do {
        let regexRange = (replaced as NSString).range(of: replaced)
        let regex = try NSRegularExpression(pattern: pattern, options: [])
        let matches = regex.matches(in: replaced, options: [], range: regexRange)
        return matches.count == 1 && matches.first!.range == regexRange
    }
    catch {}

    return false
}

If you don't want to allow decimal or negative numbers you have to replace tow variable with next line

let allowDecimal = ""
let allowSign = ""
feca
  • 1,119
  • 16
  • 14
1

For allow some charactors

func CheckAddress(string:String) -> Bool  {
        let numberOnly = NSCharacterSet.init(charactersIn: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-@,&#/")
        let stringFromTextField = NSCharacterSet.init(charactersIn: string)
        return numberOnly.isSuperset(of: stringFromTextField as CharacterSet)
    }

print("\(CheckAddress(string: "123"))") //True
print("\(CheckAddress(string: "asdf-"))") //True
print("\(CheckAddress(string: "asd123$"))") //false
Ilesh P
  • 3,940
  • 1
  • 24
  • 49
0

This is a more readable version that will do "0-9" plus ".":

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

    let existingTextHasDecimal = textField.text?.rangeOfString(".")
    let replacementTextHasDecimal = string.rangeOfString(".")
    let replacementTextAllCharacters = NSCharacterSet(charactersInString: string)
    let replacementTextOnlyDigits = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(replacementTextAllCharacters)

    if replacementTextHasDecimal != nil && existingTextHasDecimal != nil {
        return false
    }else{
        if replacementTextOnlyDigits == true {
            return true
        }else if replacementTextHasDecimal != nil{
            return true
        }else{
            return false
        }
    }
}
Enraged
  • 9
  • 1
  • This fails in many instances. This doesn't take into account the user selecting some existing text before typing or pasting in new text. – HangarRash Mar 17 '23 at 20:35
0

You can use shouldChangeCharactersInRange along with String extension method to check if the input string is number or not.

extension String  {

    var isNumber : Bool {
        get{
            return !self.isEmpty && self.stringWithoutWhitespaces.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
        }
    }

    var stringWithoutWhitespaces: String {
        return self.replacingOccurrences(of: " ", with: "")
    }

}

//Mark: shouldChangeCharactersInRange
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    // return true if the string only contains numeric characters
    let isValid = string.stringWithoutWhitespaces.isNumber 
    return valid
}
Suhit Patil
  • 11,748
  • 3
  • 50
  • 60
0

Dead simple solution for Double numbers (keep it mind that this is not the best user-friendly solution), in your UITextFieldDelegate delegate:

func textField(_ textField: UITextField,
               shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool {
        guard let currentString = textField.text as NSString? else {
            return false
        }
        let newString = currentString.replacingCharacters(in: range, with: string)
        return Double(newString) != nil
}
Tomasz Wójcik
  • 955
  • 10
  • 23
0

An approach that solves both decimal and Int:

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let currentText = textField.text
    let futureString = currentText.substring(toIndex: range.location) + string + currentText.substring(fromIndex: range.location + range.length)
    
    if futureString.count == 0 {
        return true
    }
    
    if isDecimal {
        if let numberAsDouble = Double(futureString), numberAsDouble.asPrice.count >= futureString.count {
            return true
        }
    } else if let numberAsInt = Int(futureString), "\(numberAsInt)".count == futureString.count {
        return true
    }
    
    return false
}
Tomer
  • 4,382
  • 5
  • 38
  • 48
0

When copying and pasting, there is a possibility of accidentally entering duplicate decimal points in numeric values. The following solution ensures that only numeric values and a single decimal point are allowed.

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let allowedCharacterSet = CharacterSet(charactersIn: "0123456789.")
        let replacementStringCharacterSet = CharacterSet(charactersIn: string)
        let isNumeric = allowedCharacterSet.isSuperset(of: replacementStringCharacterSet)
        
        if !isNumeric {
            return false
        }
        
        let currentText = textField.text ?? ""
        
        if string.contains(".") {
            // Check if the text already contains a dot
            let containsDot = currentText.contains(".")
            if containsDot {
                return false
            }
        }
        
        return true
    }
    
Rashid Latif
  • 2,809
  • 22
  • 26
-1

//Only accept decimal numbers as input, [ SWIFT 3.0 ]

func textField(_ shouldChangeCharactersIntextField: 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: "")

        return string == filtered
}
-1

Swift 3

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if textField==yourTextFieldOutlet {
                if(CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: yourTextFieldOutlet.text!))){
//if numbers only, then your code here
                }
                else{
                showAlert(title: "Error",message: "Enter Number only",type: "failure")
                }
            }
    return true
    }
ArgaPK
  • 455
  • 1
  • 9
  • 22
  • This only checks the previous value of the text field. This makes no attempt to validate the newly changed text. – HangarRash Mar 17 '23 at 20:45
-2

First add delegate and keyBoradType of textField

textField.delegate=self; textField.keyboardType = UIKeyboardTypeNumberPad;

Than have to use the textField.delegate method like so -

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

  if ([string intValue])
  {
        return YES;
  }

  return NO;
}
Blind Ninja
  • 1,063
  • 13
  • 28
-2

Updated Cian's response above to Swift 3:

func textField(textField: UITextField,shouldChangeCharactersInRange range: NSRange,replacementString string: String) -> Bool { let newCharacters = NSCharacterSet(charactersIn: string) let boolIsNumber = NSCharacterSet.decimalDigits.isSuperset(of:newCharacters as CharacterSet) if boolIsNumber == true { 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 } } }

Jay
  • 594
  • 10
  • 23
  • This could be lot better. you could use Characterset instead of NSCHaracterset. Not a proper conversion – CalZone Nov 09 '16 at 17:27
-2

In case someone wants only "English" letters or numbers, there is ACCII Capable option in the Keyboard type list in the Attributes Inspector enter image description here

fullmoon
  • 8,030
  • 5
  • 43
  • 58