如何限制UITextField在Swift中仅使用数字?
我希望用户只能在UITextField
input数值。 在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
delegate
和keyBoradType
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 }