Как проверить текстовые поля в UIAlertController?

Может ли кто-нибудь сказать мне, как проверить UITextFields внутри UIAlertController?

Мне нужно, чтобы пользователь не нажал "Сохранить", если оба поля не введены.

Вот мой код:

@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._%+-][email protected][A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"

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

Ответы

Ответ 1

Самый элегантный способ - использовать

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)

Ответ 2

Это можно сделать, расширив UIAlertViewController:

extension UIAlertController {

    func isValidEmail(_ email: String) -> Bool {
        return email.characters.count > 0 && NSPredicate(format: "self matches %@", "[a-zA-Z0-9._%+-][email protected][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)
}

enter image description here

Ответ 3

Это может быть достигнуто с помощью 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._%+-][email protected][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
}

Ответ 4

Вы можете использовать нижеприведенный код для проверки TextFields в 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._%+-][email protected][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 ([email protected] 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];

Ответ 5

Пример Swift 4.0

Это основано на ответе Михаила Исаева. Мне пришлось немного изменить его, чтобы кнопка "Сохранить" НЕ была активной. Я пробовал с текстом заполнителя и без него. В конце концов, для того, чтобы начать, нужно было специально инактивировать Save. В моем случае я решил использовать заголовок предупреждения, а не текст заполнителя. Но это сработало одинаково.

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)

Ответ 6

Зарегистрируйтесь для уведомлений об изменении текстового поля и подтвердите наличие текстовых полей:

//...
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)
//...

Ответ 7

Я реализовал подкласс UIAlertController, который позволяет добавлять обработчик в текстовые поля при добавлении его в предупреждение:

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

Поэтому для вашего случая единственной дополнительной возможностью, которую нужно добавить, является вызов функции isValidEmail в обработчике textChangeAction:

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

Ответ 8

Во-первых, вам нужно добавить некоторые переменные в ваш класс:

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
}

Ответ 9

После того, что @Kupendiran представил для проверки ввода электронной почты с помощью UIAlertController. Вот версия, которая работает с Objective-C и более новым форматом UIAlertController, поскольку UIAlertView теперь обесценивается.

Шаг 1. добавьте следующие файлы.h и.m с другими свойствами и переменными

.час

@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._%+-][email protected][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 ([email protected] 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];