【问题标题】:How to validate UITextfield that satisfies 5 different conditions using shouldChangeCharactersInrange method?如何使用 shouldChangeCharactersInrange 方法验证满足 5 个不同条件的 UITextfield?
【发布时间】:2019-08-12 06:31:14
【问题描述】:

我正在尝试实时验证密码文本字段(Swift 4.2 和 Xcode 10.2.1)。

我的问题是如何验证 UITextField 的 shouldChangeCharactersInrange 方法中列出的条件?

  • 最少 8 个字符
  • 最多 50 个字符
  • 最少 1 个字母
  • 最少 1 个号码
  • 无特殊字符

此外,所有 4 条验证消息的左侧都会有一个灰色刻度图像。只要条件不满足,图像就会被灰色打勾。如果验证成功,刻度图像将变为绿色。

当我点击屏幕上的确认按钮时,我将不得不调用设置新密码 API。当在 shouldChangeCharactersInrange 方法中满足上述所有条件时,我正在考虑将 bool isValidationSuccess 设置为 true。

在点击确认按钮时,只有当 isValidationSuccess 为 true 时才会调用 api。

这是我到目前为止所管理的。你能帮帮我吗?

// MARK: - TextField delegate methods
extension SetNewPasswordViewController: UITextFieldDelegate {

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
        let minPasswordLength = 8
        let currentString: NSString = newPasswordTextfield.text! as NSString
        let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString

        if newString.length < minPasswordLength {
            minimumCharacterValidationImage.isHighlighted = false
        } else {
            minimumCharacterValidationImage.isHighlighted = true
        }

        return true
    }

}

【问题讨论】:

  • 如果您的方法返回布尔值,为什么要使用.replacingCharacters?我想你可以使用range,比如:return newPasswordTextfield.text.range(of: "^(?=\\D*\\d)(?=\\d*[A-Za-z])[A-Za-z0-9]{8,50}$", options: .regularExpression) != nil
  • @WiktorStribiżew:能否验证我找到的解决方案?我已将其添加为答案。

标签: ios swift regex uitextfield


【解决方案1】:

我根据提供的答案创建了一个正则表达式,它可以工作。请你们验证一下。

  • 最少 8 个字符
  • 最多 50 个字符
  • 最少 1 个字母
  • 最少 1 个号码
  • 无特殊字符

普通类

class Common: NSObject {

        // MARK: - Password TextField Validations
        static func isValidPassword(_ input: String) -> Bool {
            print("validate Password: \(input)")
            let passwordRegex = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,50}$"
            return NSPredicate(format: "SELF MATCHES %@", passwordRegex).evaluate(with: input)
        }
    }

ViewController 代码

// MARK: - TextField delegate methods
extension SetNewPasswordViewController: UITextFieldDelegate {

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
        if textField == newPasswordTextfield {

            if let text = newPasswordTextfield.text,
                let textRange = Range(range, in: text) {
                let updatedText = text.replacingCharacters(in: textRange,
                                                           with: string)
                if Common.isValidPassword(updatedText) == true {
                    minimumCharacterValidationImage.isHighlighted = true
                    minimumAlphabetValidationImage.isHighlighted = true
                    minimumNumberValidationImage.isHighlighted = true
                    noSpecialCharacterValidationImage.isHighlighted = true
                    minimumCharacterValidationImage.isHighlighted = true
                    confirmButton.backgroundColor = UIColor(red:0, green:0.5, blue:0.54, alpha:1)
                    isValidPasswordStatus = true
                } else {
                    minimumCharacterValidationImage.isHighlighted = false
                    minimumAlphabetValidationImage.isHighlighted = false
                    minimumNumberValidationImage.isHighlighted = false
                    noSpecialCharacterValidationImage.isHighlighted = false
                    confirmButton.backgroundColor = UIColor(red:0.4, green:0.47, blue:0.5, alpha:1)
                    isValidPasswordStatus = false
                }
            }

        }
        return true
    }

}

编辑:由于没有其他答案,并且上述答案适用于指定条件,我将自己的答案标记为已接受的答案。为了清楚起见,我使用 Wiktor Stribiżew 的 cmets 找到了解决方案

【讨论】:

  • 仅当 isValidPasswordStatus 为 true 时才会调用按钮操作中的 API 调用。
  • 如果您将NSPredicateMATCHES 一起使用,则在开始/结束时不需要正则表达式中的锚点。另外,使用对比原理。此外,\d 匹配的次数多于 [0-9]。使用let passwordRegex = "(?=[^A-Za-z]*[A-Za-z])(?=[^0-9]*[0-9])[A-Za-z0-9]{8,50}"
  • @WiktorStribiżew 我已经更新了正则表达式。我还有一个问题。每当特定验证成功时,如何更改 ImageViews 的 isHighlightedvalue?目前,必须传递整个正则表达式才能使“if Common.isValidPassword(updatedText)”条件为真。我的意思是,如果输入单个数字,“minimumNumberValidationImage”应该会突出显示。
  • 然后一步一步地做每个验证,不要使用塞满前瞻的正则表达式。
【解决方案2】:

为此使用正则表达式。

func isValidPassword() -> Bool {
    let passwordRegex = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,50}$"
    return NSPredicate(format: "SELF MATCHES %@", passwordRegex).evaluate(with: self)
}

extension SetNewPasswordViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
        if textField == passwordTextField {
            if passwordTextField.isValidPassword == true
            {
                return true
            }else{
                return false
            }
        }
        return true
    }
}

【讨论】:

  • 我已经修改了你的答案并找到了解决方案。我不明白这种情况是如何运作的。 (如果 passwordTextField.isValidPassword == true)我们必须将密码文本字段文本传递给正则表达式函数并验证该字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-29
  • 1970-01-01
相关资源
最近更新 更多