【问题标题】:How to restrict UITextField to take only numbers in Swift?如何限制 UITextField 在 Swift 中只接受数字?
【发布时间】:2015-06-22 06:06:12
【问题描述】:

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

有没有办法限制用户在UITextField 中只输入数值?

【问题讨论】:

标签: ios iphone swift ipad uitextfield


【解决方案1】:

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

【讨论】:

  • 你的视图控制器应该符合UITextFieldDelegate,在viewDidLoad中放入yourNumbersTextField.delegate = self
  • 什么是范围?
  • 你为什么没有提到 UITextFieldDelegate??
  • @user924 范围由 UITextField 委托方法返回
  • @user924 提到 UITextFieldDelegate 是基本要求
【解决方案2】:

这是我的 2 美分。 (仅在 Swift 2 上测试)

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
}

【讨论】:

  • 如何限制 UITextfield 只接收数字并限制 6 到 8 之间的数字数量?
  • 您可以将aSet 设置为CharacterSet.decimalDigits.invertedSet
  • 非常适合我的需求。谢谢。
  • 你为什么没有提到 UITextFieldDelegate??
  • 您还应该添加对text == "" 的检查,以便用户可以向后删除文本。
【解决方案3】:

在 swift 4.1 和 Xcode 9.4.1 中

UITextFieldDelegate 添加到您的班级

class YourViewController: UIViewController, UITextFieldDelegate

然后在你的 viewDidLoad()

中编写这段代码
mobileNoTF.delegate = self

编写此文本字段委托函数

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

【讨论】:

  • 我该如何修复Binary operator '==' cannot be applied to operands of type 'UITextField' and '() -> ()'
  • @iOS,它是如何工作的?我已经添加了所有内容,但我仍然可以输入任何内容。该字段允许任何字符,并且不会触发 textField 函数。
【解决方案4】:

斯威夫特 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
        }
    }
}

【讨论】:

  • 谢谢 - 太好了(我一直在寻找只允许 1 个“.”的解决方案)
【解决方案5】:

仅限 iPhone 的解决方案

在您从中获取这些值的任何 UITextField 中,您都可以指定当有人在文本字段内触摸时想要显示的键盘类型。

例如纯数字键盘。

喜欢这个截图:

iPad

iPad 不支持数字键盘,因此您可以选择不支持 iPad、验证提交后的字段,或者按照此处的其他建议之一在 iPad 上运行时创建相同的行为。

【讨论】:

  • 这不能回答问题。即使使用数字键盘,iOS 也允许用户将非数字值粘贴到 UITextField 或允许 iPad 将键盘从数字切换。
  • 这是这个问题的简单答案!!没有正确答案!我知道!
  • 这不是问题的任何答案,既不简单也不恰当。问题不是询问如何更改键盘类型。问题询问如何限制输入。这些是不同的。
  • 问题是:如何限制 UITextField 在 Swift 中只取数字?所以当你的键盘类型是数字键盘时,显然满足要求。
  • OP 明确要求提供另一种解决方案,而不是更改键盘类型。 “在 iPhone 上我们可以显示数字键盘,但在 iPad 上用户可以切换到任何键盘。”
【解决方案6】:

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

【讨论】:

  • 这是我唯一可以工作的(限制为一位小数),太棒了!
  • 实际上我对其进行了修改以允许使用一个逗号(根据 FR)
  • 请注意,并非所有语言环境都使用“.”作为小数分隔符。您可能想改用 Locale.current.decimalSeparator。
【解决方案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
}

即使用户切换键盘或尝试将非数字字符串粘贴到文本字段中,此解决方案也可以工作。

确保设置相应文本字段的delegate 属性。

【讨论】:

  • 使用[string intValue] 如上一个答案中所建议的将不起作用,因为即使string 包含非数字字符,该属性也可能为真(非零)。根据文档,intValue 仅在“字符串不以数字的有效十进制文本表示开头”时为 0。
【解决方案8】:

使用数字格式化程序

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
 }

【讨论】:

  • 谢谢!这个比许多其他的要好,因为它允许小数但不能任意使用小数。
【解决方案9】:

这是一个简单的解决方案,您需要在控制器中将“编辑更改”事件连接到此方法

斯威夫特 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()
        }
    }
}

【讨论】:

  • 如果代理已经被 Rx 使用,这是一个很好的解决方案。
  • 如果我添加空格或符号会崩溃
【解决方案10】:

像这样扩展你的视图控制器:

class MyViewController: UIViewController, UITextFieldDelegate

在 viewDidLoad 函数中,像这样扩展到您的文本字段:

myTextField.delegate = self

然后使用下面的函数:

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
}

这将确保用户只能输入十进制数字。

斯威夫特 4 + 只接受号码 并接受一个分隔符

【讨论】:

    【解决方案11】:

    第一个你必须继承你自己的 UITextFieldDelegate 类 类

    class ViewController: UIViewController, UITextFieldDelegate {
    

    第二次添加 IBOutlet

    @IBOutlet weak var firstName: UITextField!
    

    第三你必须确保这个对象正在使用

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

    【讨论】:

      【解决方案12】:

      //除了这些,您只需将键盘更改为数字类型

      yourtextfield.keyboardType = UIKeyboardType.numberPad
      

      【讨论】:

      • 这无法解决此问题,因为用户可以将非数字字符粘贴到文本字段中。
      • 然后你可以使用号码扩展
      【解决方案13】:

      虽然这些解决方案中的大多数都可以使用,但请注意,在某些本地化版本中,小数用“,”而不是“。”分隔。

      更简洁的方法是

      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
      }
      

      【讨论】:

        【解决方案14】:

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

        【讨论】:

          【解决方案15】:

          这是一个更清洁的解决方案:

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

          对于小数只需添加.,例如123456789.

          【讨论】:

          • 这有点好,但与这个使用 UITextfiled 委托相比。
          【解决方案16】:

          设置 KeyboardType 属性:- 数字键盘 TextField Delegate 请写下代码

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

          数字不能从0开始,输入数字+ve。

          【讨论】:

            【解决方案17】:

            我在阅读 Big Nerd Ranch 书时实际上已经这样做了,我的解决方案是:

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

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

            【讨论】:

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

              【讨论】:

                【解决方案19】:

                要只允许数字和一个小数运算符,您可以使用以下解决方案:

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

                【讨论】:

                  【解决方案20】:
                  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
                          }
                  

                  上面的代码在 swift 3 中工作
                  NSCharacterSet.decimalDigits
                  您也只能使用字母
                  NSCharacterSet.字母
                  大写、小写和、字母数字、空格 使用相同的代码 或See the Link

                  【讨论】:

                    【解决方案21】:

                    我认为你可以通过实现 UITextInputTraits 协议,可选的 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
                            }
                        } 
                    }
                    

                    【讨论】:

                      【解决方案22】:

                      这是一个可读性更强的版本,将“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
                              }
                          }
                      }
                      

                      【讨论】:

                        【解决方案23】:

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

                        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
                        }
                        

                        【讨论】:

                          【解决方案24】:

                          以下是我在 Swift 3.0 中使用的代码,改编自 H 先生的代码。差异是因为:

                          a) Swift 3.0 中的委托函数声明已更改。 New declaration here

                          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
                          
                          }
                          

                          【讨论】:

                            【解决方案25】:

                            我已经编辑了 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
                                    }
                                }
                            }
                            

                            【讨论】:

                              【解决方案26】:

                              如果您想允许小数分隔符和/或负数,您可以使用此代码。 但此代码允许示例:“34”。 (末尾的小数分隔符)同时更改文本。所以你必须添加一些代码示例:textFieldShouldReturn 或 textFieldShouldEndEditing 委托函数。

                              用 Swift 4 编写的代码,但我认为这与 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
                              }
                              

                              如果你不想允许小数或负数,你必须用下一行替换两个变量

                              let allowDecimal = ""
                              let allowSign = ""
                              

                              【讨论】:

                                【解决方案27】:

                                允许一些字符

                                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
                                

                                【讨论】:

                                  【解决方案28】:

                                  以下解决方案有两个好处:

                                  1. 这是一行代码
                                  2. 它限制输入,以便输入字段中的整体文本是有效数字。其他解决方案将数字限制为有效数字,但这会导致用户能够输入“4...5”
                                      func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
                                          return NumberFormatter().numberFrom(text: (textField.text ?? "") + string) != nil
                                      }
                                  

                                  【讨论】:

                                    【解决方案29】:
                                    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
                                    
                                      }
                                    

                                    【讨论】:

                                      【解决方案30】:
                                      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
                                          }
                                      }
                                      

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

                                      【讨论】:

                                        猜你喜欢
                                        • 1970-01-01
                                        • 2017-11-02
                                        • 1970-01-01
                                        • 2012-05-30
                                        • 2014-06-06
                                        • 1970-01-01
                                        • 1970-01-01
                                        • 1970-01-01
                                        • 1970-01-01
                                        相关资源
                                        最近更新 更多