如何限制UITextField在Swift中仅使用数字?

我希望用户只能在UITextFieldinput数值。 在iPhone上,我们可以显示数字键盘,但在iPad上,用户可以切换到任何键盘。

有什么办法来限制用户在UITextField只input数值吗?

这是我的2分。 (仅在Swift 2上testing)

 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 } 

这只是一点点严格。 没有小数点。

希望能帮助到你 :)

PS:我假设你照顾代表无论如何。

更新: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 } 

解决scheme为SWIFT 3.0及以上

 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) } 

Swift 2.0

只允许数字和一个“。” 小数在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 } } } 

在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 } } } 
 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 } 

即使用户切换键盘或尝试将非数字string粘贴到文本字段中,该解决scheme也可以正常工作。

确保设置适当的文本字段的delegate属性。

我在“大书呆子牧场”一书中做了实际的工作,我的解决scheme是:

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

这只允许数字0-9,允许“。” 而且更复杂,因为你只能允许一个“。”

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if let numRange = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet()) { return false } else { return true } } 

经过3.0testing

 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 } 

我认为你可以通过实现UITextInputTraits协议强制改变键盘types,可选的var keyboardType

 //class ViewController: UIViewController, UITextInputTraits { @IBOutlet weak var textFieldKeyboardType: UITextField!{ didSet{ textFieldKeyboardType.keyboardType = UIKeyboardType.NumberPad } } var keyboardType: UIKeyboardType { get{ return textFieldKeyboardType.keyboardType } set{ if newValue != UIKeyboardType.NumberPad{ self.keyboardType = UIKeyboardType.NumberPad } } } 

虽然这些解决scheme大部分都能正常工作,但请注意,在某些本地化中,小数点分隔为“,”而不是“。”。

更干净的方式来做到这一点

 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 } 

好像没有足够的答案,这是我的。 我认为每个允许使用小数点分隔符的示例在本地化,退格或复制/粘贴中都是有缺陷的。

 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 } 

要仅允许数字和一个小数运算符,可以使用此解决scheme:

 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) } 

以下是我用H代码修改Swift 3.0的代码。 差异是因为:

a)Swift 3.0中委托函数声明已经改变。 新的声明在这里

b)NSCharacterSet声明已经改变。

 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 } 
 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 } 

在上面的代码中是快速的3
NSCharacterSet。 decimalDigits
你也只是用字母
NSCharacterSet。 快报
大写,小写字母数字,空格使用相同的代码或查看链接

 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 } 

这是一个更可读的版本,将做“0-9”加“。”:

 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 } } } 
 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 } } 

如果有的话,把这个函数放在你的“提交”或“保存”方法中。

您可以使用shouldChangeCharactersInRange和String扩展方法来检查inputstring是否为数字。

 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 } 

Double数字的死简单的解决scheme(请记住,这不是最好的用户友好的解决scheme),在你的UITextFieldDelegate委托:

 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 } 

我编辑了Raj Joshi的版本,以允许一个点或一个逗号:

 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 } } } 

如果要允许小数点分隔符和/或负数,则可以使用此代码。 但是这个代码允许例子:“34.” (最后一个十进制分隔符),同时改变文本。 所以你必须添加一些代码示例:textFieldShouldReturn或textFieldShouldEndEditing委托函数。

在Swift 4编写的代码,但我assueme这是与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 } 

如果您不想允许小数或负数,则必须用下一行replace两个variables

 let allowDecimal = "" let allowSign = "" 

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 } 

首先添加textField delegatekeyBoradType

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

不得不使用像这样的textField.delegate方法 –

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

更新Cian对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 } } }

//只接受十进制数字作为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 }