如何限制UITextField在Swift中只接受数字?


73

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

有什么方法可以限制用户仅在UITextField?中输入数字值?


您必须更改输入的文本。
盲人忍者

是的,但是即使在设置了数字键盘之后,在ipad中,用户也可以输入字母

您更改文字是什么意思?


Answers:


79

这是我的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之间的数字量?
Marco Almeida'5

您可以设置aSetCharacterSet.decimalDigits.invertedSet
yesthisisjoe

非常适合我的需求。谢谢。
杨扬

为什么你没有提到UITextFieldDelegate?
user924

您还应该添加一个检查,text == ""以便用户可以向后删除文本。
thecoolwinter

79

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

4
您的视图控制器应符合UITextFieldDelegate,在viewDidLoad中放置yourNumbersTextField.delegate = self
Manee.OH

什么是范围?
user924

为什么你没有提到UITextFieldDelegate?
user924

@ user924范围是由UITextField委托方法返回的
Hiren Panchal,

@ user924提到UITextFieldDelegate是基本要求
Hiren Panchal

25

在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 '() -> ()'
newswiftcoder

@iOS,它如何工作?我已经添加了所有内容,但仍然可以输入任何内容。该字段允许任何字符,并且不会触发textField函数。
Smit

13

斯威夫特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“。”的解决方案)
derdida '16

10

仅限iPhone的解决方案

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

EG数字键盘。

喜欢这个截图:

在此处输入图片说明

平板电脑

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


13
这不能回答问题。即使使用数字键盘,iOS仍允许用户将非数字值粘贴到UITextField中,或允许iPad将键盘从数字切换为非数字。
罗布

这是这个问题的简单答案!没有正确的答案!我知道!
贾米尔·哈斯宁·塔米姆

2
这不是对这个问题的任何答案,既简单又不合适。问题在于如何更改键盘类型。问题询问如何限制输入。那些是不同的。
罗布

问题是:如何限制UITextField在Swift中只能取数字?因此,当您的键盘类型是数字键盘时,显然可以满足要求。
贾米尔·哈斯宁·塔米姆

1
OP明确要求提供另一种解决方案,而不是更改键盘类型。“在iPhone上,我们可以显示数字键盘,但是在iPad上,用户可以切换到任何键盘。”
Ferdz

9

在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)
克里斯·艾林森

4
请注意,并非所有语言环境都使用“。” 作为小数点分隔符。您可能要改用Locale.current.decimalSeparator。
Volker Voecking

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适当的文本字段的属性。


1
[string intValue]如先前答案中所建议的那样使用将不起作用,因为即使string包含非数字字符,该属性也可能为true(非零)。根据文档,intValue只有在“字符串不是以数字的有效十进制文本开头的情况下,才为0”。
ndmeiri 2015年

5

使用数字格式器

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

谢谢!这个比其他很多都好,因为它允许十进制数字,但不能随意使用十进制。
安迪·温斯坦

5

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

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
}

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

Swift 4 +仅接受数字并接受一个分隔符


4

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

斯威夫特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使用,则是一个很好的解决方案。
S-

如果我添加空格或符号,它将崩溃
karthikeyan 19/09/18

3

尽管大多数这些解决方案都可以使用,但是请注意,在某些区域中,小数以“,”而不是“”分隔。

更干净的方法是

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
}

3

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

3

1您必须使用自己的类继承UITextFieldDelegate类

class ViewController: UIViewController, UITextFieldDelegate {

2添加一个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


      }
  }

3

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

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

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


有点不错,但与此相比,使用UITextfiled委托。
iOS

3

设置KeyboardType属性:-数字键盘TextField代理,请在下面的代码中编写

  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。


2

在阅读《大书呆子牧场》一书时,我实际上已经做到了,我的解决方案是:

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

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

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


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

2

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

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

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
        }

上面的代码在3
NSCharacterSet中工作。decimalDigits
您还仅使用字母
NSCharacterSet。字母
大写字母,小写字母字母数字,空格 使用相同的代码,或 参见链接


2

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

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

1

我认为您可以通过实现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
        }
    } 
}

1

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

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
}

1

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

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

}

1

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

1

对于允许一些角色

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

0
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

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

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

如果有此功能,请将其放在“提交”或“保存”方法中。


0

您可以将shouldChangeCharactersInRange和String扩展方法一起使用,以检查输入的字符串是否为数字。

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
}

0

Double在您的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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.