【问题标题】:How do I validate TextFields in an UIAlertController?如何验证 UIAlertController 中的文本字段?
【发布时间】:2015-06-02 12:59:38
【问题描述】:

谁能告诉我如何在UIAlertController 中验证UITextFields

我需要它来防止用户点击“保存”,除非两个字段都输入。

到目前为止,这是我的代码:

@IBAction func btnStart(sender: AnyObject) {
    var alert = UIAlertController(title: "New user",
        message: "Add a new user",
        preferredStyle: .Alert)

    let saveAction = UIAlertAction(title: "Save",
        style: .Default) { (action: UIAlertAction!) -> Void in

            self.textFieldName = alert.textFields![0] as UITextField
            self.textFieldEmail = alert.textFields![1] as UITextField
            self.saveUser(self.textFieldName.text, email: self.textFieldEmail.text)
            self.tableView.reloadData()
    }

    saveAction.enabled = false

    let cancelAction = UIAlertAction(title: "Cancel",
        style: .Default) { (action: UIAlertAction!) -> Void in
    }

    alert.addTextFieldWithConfigurationHandler {
        (textFieldName: UITextField!) in
        textFieldName.placeholder = "Enter full name"
    }

    alert.addTextFieldWithConfigurationHandler {
        (textFieldEmail: UITextField!) in
        textFieldEmail.placeholder = "Enter valid email adress"
        textFieldEmail.keyboardType = .EmailAddress

    }
    alert.addAction(saveAction)
    alert.addAction(cancelAction)

    presentViewController(alert,
        animated: true,
        completion: nil)
}

这是我验证电子邮件字段的函数:

func isValidEmail(testStr:String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"

    if let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx) {
        return emailTest.evaluateWithObject(testStr)
    }
    return false
}

【问题讨论】:

标签: ios swift uitextfield uialertview


【解决方案1】:

这可以通过扩展UIAlertViewController来完成:

extension UIAlertController {

    func isValidEmail(_ email: String) -> Bool {
        return email.characters.count > 0 && NSPredicate(format: "self matches %@", "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,64}").evaluate(with: email)
    }

    func isValidPassword(_ password: String) -> Bool {
        return password.characters.count > 4 && password.rangeOfCharacter(from: .whitespacesAndNewlines) == nil
    }

    func textDidChangeInLoginAlert() {
        if let email = textFields?[0].text,
            let password = textFields?[1].text,
            let action = actions.last {
            action.isEnabled = isValidEmail(email) && isValidPassword(password)
        }
    }
}

// ViewController
override func viewDidLoad() {
    super.viewDidLoad()

    let alert = UIAlertController(title: "Please Log In", message: nil, preferredStyle: .alert)

    alert.addTextField {
        $0.placeholder = "Email"
        $0.addTarget(alert, action: #selector(alert.textDidChangeInLoginAlert), for: .editingChanged)
    }

    alert.addTextField {
        $0.placeholder = "Password"
        $0.isSecureTextEntry = true
        $0.addTarget(alert, action: #selector(alert. textDidChangeInLoginAlert), for: .editingChanged)
    }

    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))

    let loginAction = UIAlertAction(title: "Submit", style: .default) { [unowned self] _ in
        guard let email = alert.textFields?[0].text,
            let password = alert.textFields?[1].text
            else { return } // Should never happen

        // Perform login action
    }

    loginAction.isEnabled = false
    alert.addAction(loginAction)
    present(alert, animated: true)
}

【讨论】:

  • 很好的答案,唯一需要改变的是在textDidChangeInLoginAlert() 函数之前添加@objc
【解决方案2】:

最优雅的方式是使用

NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange...

Swift 3.0 示例

let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    let saveAction = UIAlertAction(title:"Save", style: .destructive, handler: { (action) -> Void in

    })
    alert.addAction(saveAction)
    alert.addTextField(configurationHandler: { (textField) in
        textField.placeholder = "Enter something"
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in
            saveAction.isEnabled = textField.text!.length > 0
        }
    })
    present(alert, animated: true, completion: nil)

【讨论】:

  • 您是否需要在某个时候移除观察者,或者尽管有观察者,但文本字段会正常释放吗?
  • 如果您的应用面向 iOS 9.0 及更高版本或 macOS 10.11 及更高版本,则无需在其 dealloc 方法中取消注册观察者。 (耶!)在此处查看文档:developer.apple.com/documentation/foundation/notificationcenter/…
【解决方案3】:

Swift 4.0 示例

这是基于 Mihael Isaev 的回答。我不得不对其进行一些更改以使“保存”按钮不立即处于活动状态。我尝试使用和不使用占位符文本。最后,不得不专门停用保存开始。就我而言,我选择使用警报标题而不是占位符文本。但是,无论哪种方式,它的工作原理都是一样的。

let alert = UIAlertController(title: "Enter Username", message: nil, preferredStyle: .alert)

alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in}))
let saveAction = UIAlertAction(title:"Save", style: .destructive, handler: { (action) -> Void in
})
alert.addAction(saveAction)
alert.addTextField(configurationHandler: { (textField) in
    textField.text = ""
    saveAction.isEnabled = false
    NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in
        saveAction.isEnabled = textField.text!.length > 0
    }
})
self.present(alert, animated: true, completion: nil)

【讨论】:

  • 对于 Swift 5,只需从 forName 参数中删除 NSNotification.Name.。我还建议将 textFieldsaveAction 都传递为 weak 以防止循环
【解决方案4】:

对于 Swift 4.2 (NSNotification.Name.UITextFieldTextDidChange) 更新:

let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    let saveAction = UIAlertAction(title:"Save", style: .destructive, handler: { (action) -> Void in

    })
    alert.addAction(saveAction)
    alert.addTextField(configurationHandler: { (textField) in
        textField.placeholder = "Enter something"
        NotificationCenter.default.addObserver(forName: UITextField.textDidChangeNotification, object: textField, queue: OperationQueue.main) { (notification) in
            saveAction.isEnabled = textField.text?.count > 0
        }
    })
    present(alert, animated: true, completion: nil)

【讨论】:

    【解决方案5】:

    这可以在显示警报控制器之前通过 NSNotificationCenter 来实现,你所要做的就是让通知中心观察 UITextFieldTextDidChangeNotification 的通知,你应该很好,

    下面给出的是相同的实现

    @IBAction func showAlert(sender: AnyObject) {
    
        var alert = UIAlertController(title: "New user",
            message: "Add a new user",
            preferredStyle: .Alert)
    
        let saveAction = UIAlertAction(title: "Save",
            style: .Default) { (action: UIAlertAction!) -> Void in
    
                println("do your stuff here")
        }
    
        saveAction.enabled = false
    
        let cancelAction = UIAlertAction(title: "Cancel",
            style: .Default) { (action: UIAlertAction!) -> Void in
        }
    
    
        alert.addTextFieldWithConfigurationHandler {
            (textFieldName: UITextField!) in
            textFieldName.placeholder = "Enter full name"
        }
    
        alert.addTextFieldWithConfigurationHandler {
            (textFieldEmail: UITextField!) in
            textFieldEmail.placeholder = "Enter valid email adress"
            textFieldEmail.keyboardType = .EmailAddress
    
        }
    // adding the notification observer here
     NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[0],
            queue: NSOperationQueue.mainQueue()) { (notification) -> Void in
    
                let textFieldName = alert.textFields?[0] as! UITextField
                let textFieldEmail = alert.textFields![1] as! UITextField
                saveAction.enabled = self.isValidEmail(textFieldEmail.text) &&  !textFieldName.text.isEmpty
        }
    
    
        NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[1],
            queue: NSOperationQueue.mainQueue()) { (notification) -> Void in
    
                let textFieldEmail = alert.textFields?[1] as! UITextField
                let textFieldName = alert.textFields?[0] as! UITextField
                saveAction.enabled = self.isValidEmail(textFieldEmail.text) &&  !textFieldName.text.isEmpty
        }
    
    
        alert.addAction(saveAction)
        alert.addAction(cancelAction)
    
        presentViewController(alert,
            animated: true,
            completion: nil)
    
    }
    
     //  email validation code method
    func isValidEmail(testStr:String) -> Bool {
        let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
        if let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx) as NSPredicate? {
            return emailTest.evaluateWithObject(testStr)
        }
        return false
    }
    

    【讨论】:

    • 非常感谢,这有所帮助,但行为有点奇怪。如果我先输入姓名,然后输入电子邮件,则可以,但如果我先输入电子邮件,然后输入姓名,则没有任何反应。此外,当输入电子邮件并从名称字段中删除文本时,它仍然允许我发送信息:S
    • @MarkoMiletić:嗯,我刚刚给了你关于如何执行保存按钮的想法,等我更新我的答案
    • @MarkoMiletić 完成的编辑将根据您的需要进行,请查看并告诉我
    • @MarkoMiletić:有一个缺陷,所以重新编辑代码请确认
    • 是的,这就是解决方案,但是正如@keithbhunter 所写的,这两个文本字段都需要在两个通知中进行验证。非常感谢:)
    【解决方案6】:

    您可以使用下面的代码来验证 UIAlertController 中的文本字段:-

    第 1 步:

    Declare "email_TF" to your viewcontroller.h 
    
    for example: 
        @property(strong,nonatomic)UITextField *email_TF;
    

    第 2 步:

    UIAlertController *alert= [UIAlertController alertControllerWithTitle:@"Forgot Password?" message:nil preferredStyle:UIAlertControllerStyleAlert];
    [alert addTextFieldWithConfigurationHandler: ^(UITextField *textField){
        textField.placeholder= @"Enter Your Valid Email";
        textField.autocorrectionType= UITextAutocorrectionTypeYes;
        textField.keyboardType= UIKeyboardTypeEmailAddress;
    
        email_TF= textField;
    }];
    

    第 3 步:

    UIAlertAction *noButton= [UIAlertAction actionWithTitle:@"No, thanks" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action){
        //Handel no, thanks button
    }];
    [alert addAction:noButton];
    
    UIAlertAction *yesButton= [UIAlertAction actionWithTitle:@"Yes, please" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
        //Handel your yes please button action here
        NSLog(@"%@", email_TF.text);
    
        if(email_TF.text.length>0){//
    
            NSString *emailString= email_TF.text;
            NSString *emailReg= @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
            NSPredicate *emailTest= [NSPredicate predicateWithFormat:@"SELF MATCHES %@",emailReg];
    
            if(([emailTest evaluateWithObject:emailString]!=YES) || [emailString isEqualToString:@""]){
    
                UIAlertView *loginalert= [[UIAlertView alloc] initWithTitle:@"Forgot Password !" message:@"\nPlease enter valid Email (example@example.com format) ." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
                [loginalert show];
    
            }else{
    
                NSLog(@"your TextField successfully validated");
    
            }
        }else{
    
            UIAlertView *alert= [[UIAlertView alloc] initWithTitle:@"Forgot Password !" message:@"\nPlease Enter Your Email..." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
    
        }
    
    }];
    
    [alert addAction:yesButton];
    

    第 4 步:

    [self presentViewController:alert animated:YES completion:nil];
    

    【讨论】:

      【解决方案7】:

      注册文本字段更改通知并验证那里的文本字段:

      //...
      alert.addTextFieldWithConfigurationHandler {
          (textFieldEmail: UITextField!) in
          textFieldEmail.placeholder = "Enter valid email adress"
          textFieldEmail.keyboardType = .EmailAddress
      }   
      
      let textFieldValidationObserver: (NSNotification!) -> Void = { _ in
          let textFieldName = alert.textFields![0] as! UITextField
          let textFieldEmail = alert.textFields![1] as! UITextField
          saveAction.enabled = self.isValidEmail(textFieldEmail.text) && textFieldName.text.length > 0
      }
      
      // Notifications for textFieldName changes
      NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification,
          object: alert.textFields![0],  // textFieldName
          queue: NSOperationQueue.mainQueue(), usingBlock: textFieldValidationObserver)
      
      // Notifications for textFieldEmail changes
      NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification,
          object: alert.textFields![1],  // textFieldEmail
          queue: NSOperationQueue.mainQueue(), usingBlock: textFieldValidationObserver)
      
      alert.addAction(saveAction)
      //...
      

      【讨论】:

      • 我真的很陌生,所以我不太了解它,你能在我的代码中实现它吗?我在“对象:alert.textFields [1]”行上收到错误消息,上面写着“'[AnyObject]' 没有名为 'subscript' 的成员”
      • 更新了我的答案。注意隐式展开的选项。这就是我之前错过的以及导致您的错误的原因。
      • 哦,谢谢老兄!!!这成功了 :) 我通常从事前端开发工作,所以这类事情对我来说有点像中文 :D
      【解决方案8】:

      我实现了a UIAlertController subclass,它允许您在将文本字段更改添加到警报时添加处理程序:

      public class TextEnabledAlertController: UIAlertController {
        private var textFieldActions = [UITextField: ((UITextField)->Void)]()
      
        func addTextField(configurationHandler: ((UITextField) -> Void)? = nil, textChangeAction:((UITextField)->Void)?) {
          super.addTextField(configurationHandler: { (textField) in
              configurationHandler?(textField)
      
              if let textChangeAction = textChangeAction {
                  self.textFieldActions[textField] = textChangeAction
                  textField.addTarget(self, action: #selector(self.textFieldChanged), for: .editingChanged)
      
              }
          })
        }
      
        @objc private func textFieldChanged(sender: UITextField) {
          if let textChangeAction = textFieldActions[sender] {
              textChangeAction(sender)
          }
        }
      }
      

      因此,对于您的情况,唯一需要添加的是在 textChangeAction 处理程序中调用 isValidEmail 函数:

          alert.addTextField(configurationHandler: { (textField) in
              // things you want to configure on the textfield
          }) { (textField) in
              saveAction.isEnabled = isValidEmail(textField.text ?? "")
          }
      

      【讨论】:

        【解决方案9】:

        遵循@Kupendiran 提出的使用 UIAlertController 进行电子邮件输入验证的内容。这是一个使用 Objective-C 和更新的 UIAlertController 格式的版本,因为 UIAlertView 现在已弃用。

        步骤 1. 将以下内容添加到具有其他属性和变量的 .h 和 .m 文件中

        .h

        @property(strong,nonatomic)UITextField *emailAddressField;
        

        .m

        UITextField *emailAddressField;
        

        第 2 步。创建警报消息、按钮和验证过程。

        UIAlertController * alertView =   [UIAlertController
                                                   alertControllerWithTitle:@"E-Mail Address"
                                                   message:@"Enter your email address:"
                                                   preferredStyle:UIAlertControllerStyleAlert];
        
                [alertView addTextFieldWithConfigurationHandler:^(UITextField *emailTextField) {
                    emailTextField.placeholder = @"E-Mail Address";
                    emailTextField.autocorrectionType= UITextAutocorrectionTypeYes;
                    emailTextField.keyboardType= UIKeyboardTypeEmailAddress;
        
                    emailAddressField = emailTextField;
                }];
        

        第 3 步。创建警报操作

                UIAlertAction * ok= [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
                    //Handel your OK button action here
                    NSLog(@"Email Address Entered is: %@", emailAddressField.text);
        
                    //Validate email address is correct format
                    if(emailAddressField.text.length>0){//
        
                        NSString *emailString= emailAddressField.text;
                        NSString *emailReg= @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
                        NSPredicate *emailTest= [NSPredicate predicateWithFormat:@"SELF MATCHES %@",emailReg];
        
                        if(([emailTest evaluateWithObject:emailString]!=YES) || [emailString isEqualToString:@""]){
        
                            NSLog(@"Email Address Entered is not valid: %@", emailAddressField.text);
        
                            UIAlertController *badEmailAlert = [UIAlertController
                                                             alertControllerWithTitle:@"Email Address"
                                                                              message:@"\nPlease enter valid Email (example@example.com format) ."
                                                                       preferredStyle:UIAlertControllerStyleAlert];
                            [self presentViewController:badEmailAlert animated:YES completion:nil];
        
                            UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault
                                                                           handler:^(UIAlertAction * action) {
                                                                               [badEmailAlert dismissViewControllerAnimated:YES completion:nil];
                                                                               [self presentViewController:alertView animated:YES completion:nil];
                                                                           }];
                            [badEmailAlert addAction:cancel];
        
        
                        }else{
        
                            NSLog(@"your TextField successfully validated");
        
                        }
                    }else{
        
                        [self presentViewController:alertView animated:YES completion:nil];
        
                    }
        
                }];
                [alertView addAction:ok];
        
        
                //Handel your Cancel button action here
                UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault
                                                               handler:^(UIAlertAction * action) {
                                                                   [alertView dismissViewControllerAnimated:YES completion:nil];
                                                               }];
                [alertView addAction:cancel];
        

        第 4 步。在屏幕上显示警报消息

        [self presentViewController:alertView animated:YES completion:nil];
        

        【讨论】:

          【解决方案10】:

          首先,您需要在类中添加一些变量:

          private weak var saveAction : UIAlertAction?
          private weak var textFieldName : UITextField?
          private weak var textFieldEmail : UITextField?
          private var validName = false
          private var validEmail = false
          

          然后,当你要配置警报控制器时(我只粘贴了需要更改的东西):

              alert.addTextFieldWithConfigurationHandler {
                  (textFieldName: UITextField!) in
                  textFieldName.placeholder = "Enter full name"
                  textFieldName.delegate = self
                  self.textFieldName = textFieldName
              }
              alert.addTextFieldWithConfigurationHandler {
                  (textFieldEmail: UITextField!) in
                  textFieldEmail.placeholder = "Enter valid email adress"
                  textFieldEmail.keyboardType = .EmailAddress
                  textFieldEmail.delegate = self
                  self.textFieldEmail = textFieldEmail
              }
          
              let saveAction = UIAlertAction(title: "Save",
                  style: .Default) { (action: UIAlertAction!) -> Void in
                  // here you are sure the name and email are correct
                  let name = (alert.textFields[0] as! UITextField).text
                  let email = (alert.textFields[1] as! UITextField).text
              }
          
              saveAction.enabled = false
              self.saveAction = saveAction
          

          最后,你应该实现这个委托方法:

          func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
          
              let newText = NSString(string: textField.text).stringByReplacingCharactersInRange(range, withString: string)
          
              if textField == self.textFieldName {
                  // validate newText for the name requirements
                  validName = self.validateName(newText)
              } else if textField == self.textFieldEmail {
                  // validate newText for the email requirements
                  validEmail = self.validateEmail(newText)
              }
          
              self.saveAction?.enabled = validEmail && validName
          
              return true
          }
          

          【讨论】:

            猜你喜欢
            • 2023-03-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多