如何使用 shouldChangeCharactersInrange 方法验证满足 5 个不同条件的 UITextfield?

Posted

技术标签:

【中文标题】如何使用 shouldChangeCharactersInrange 方法验证满足 5 个不同条件的 UITextfield?【英文标题】:How to validate UITextfield that satisfies 5 different conditions using shouldChangeCharactersInrange method? 【发布时间】: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:能否验证我找到的解决方案?我已将其添加为答案。 【参考方案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)我们必须将密码文本字段文本传递给正则表达式函数并验证该字符串。

以上是关于如何使用 shouldChangeCharactersInrange 方法验证满足 5 个不同条件的 UITextfield?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 5 - 用 X 屏蔽文本字段文本

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?