将用户输入限制为Swift中的有效十进制数

zav*_*tra 12 objective-c ipad ios swift

我已经找到了很多关于如何在objective-c中执行此操作的指南,但我希望看到更多以Swift为导向的方法.

我有一个用户输入货币价格的UITextField.文本字段调用十进制键盘.但是,在iPad上,出现的键盘有一整套非小数符号.

基本上,对于每一次按键,我都希望不能将非数字或超过一个小数的任何内容输入到字段中.如果输入小数,我想不可能输入第二个小数.如果删除小数,我想确保用户可以再次输入小数.

关于如何在swift中正确执行此操作的任何想法?

我也看到像这里发布的解决方案: 将UITextField限制为一个小数点Swift 但是我不知道在哪里放置函数或者我应该如何调用它们.每当我尝试在参数中放入NSRange时,我都会收到错误消息,表示我没有正确创建范围.

Ste*_*erg 13

这是一个简单的例子:

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self

    }

    //Textfield delegates
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return NO to not change text

        switch string {
        case "0","1","2","3","4","5","6","7","8","9":
            return true
        case ".":
            let array = Array(textField.text)
            var decimalCount = 0
            for character in array {
                if character == "." {
                    decimalCount++
                }
            }

            if decimalCount == 1 {
                return false
            } else {
                return true
            }
        default:
            let array = Array(string)
            if array.count == 0 {
                return true
            }
            return false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个好的解决方案,因为它只适用于非常有限的语言环境。并非所有用户都使用句点作为小数点分隔符,也并非所有用户都使用字符 0-9 来表示数字。如果用户将文本粘贴到文本字段中,此代码也将不起作用。 (2认同)

Lyn*_*ott 7

这通过使用NSScanner来测试新字符串是否为数字来考虑多个小数:

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

    // Get the attempted new string by replacing the new characters in the
    // appropriate range
    let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)

    if newString.length > 0 {

        // Find out whether the new string is numeric by using an NSScanner.
        // The scanDecimal method is invoked with NULL as value to simply scan
        // past a decimal integer representation.
        let scanner: NSScanner = NSScanner(string:newString)
        let isNumeric = scanner.scanDecimal(nil) && scanner.atEnd

        return isNumeric

    } else {

        // To allow for an empty text field
        return true
    }

}
Run Code Online (Sandbox Code Playgroud)


wye*_*wye 7

Swift 2版@Steve Rosenberg的解决方案

如果您不需要将输入限制为最多2个小数位(即"12.34"确定,"12.345"不正常),则在开头删除4行.

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!

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

    //Textfield delegates
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return false to not change text
        // max 2 fractional digits allowed
        let newText = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
        let regex = try! NSRegularExpression(pattern: "\\..{3,}", options: [])
        let matches = regex.matchesInString(newText, options:[], range:NSMakeRange(0, newText.characters.count))
        guard matches.count == 0 else { return false }

        switch string {
        case "0","1","2","3","4","5","6","7","8","9":
            return true
        case ".":
            let array = textField.text?.characters.map { String($0) }
            var decimalCount = 0
            for character in array! {
                if character == "." {
                    decimalCount++
                }
            }
            if decimalCount == 1 {
                return false
            } else {
                return true
            }
        default:
            let array = string.characters.map { String($0) }
            if array.count == 0 {
                return true
            }
            return false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mir*_*vik 6

Swift 3实现此 UITextFieldDelegate 方法以防止用户输入无效数字:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text = (textField.text ?? "") as NSString
    let newText = text.replacingCharacters(in: range, with: string)
    if let regex = try? NSRegularExpression(pattern: "^[0-9]*((\\.|,)[0-9]{0,2})?$", options: .caseInsensitive) {
        return regex.numberOfMatches(in: newText, options: .reportProgress, range: NSRange(location: 0, length: (newText as NSString).length)) > 0
    }
    return false
}
Run Code Online (Sandbox Code Playgroud)

它同时使用逗号或点作为小数分隔符,并允许 2 个小数位。


mis*_*bot 6

所有答案都使用'.' 作为小数的有效分隔符,但在不同的本地化中它可能是错误的.

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

    let currentText = textField.text ?? ""
    let replacementText = (currentText as NSString).replacingCharacters(in: range, with: string)

    return replacementText.isDecimal()
}


extension String{
   func isDecimal()->Bool{
       let formatter = NumberFormatter()
       formatter.allowsFloats = true
       formatter.locale = Locale.current
       return formatter.number(from: self) != nil
   }
}
Run Code Online (Sandbox Code Playgroud)