Enable UIAlertAction of UIAlertController only after input

血红的双手。 提交于 2019-11-29 02:00:24

Add following property in your header file

@property(nonatomic, strong)UIAlertAction *okAction;   

then copy the following code in your viewDidLoad method of your ViewController

self.okAction = [UIAlertAction actionWithTitle:@"OK"
                                         style:UIAlertActionStyleDefault
                                       handler:nil];
self.okAction.enabled = NO;

UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil
                                                                    message:@"Enter your text"
                                                             preferredStyle:UIAlertControllerStyleAlert];

[controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {

    textField.delegate = self;
}];

[controller addAction:self.okAction];
[self presentViewController:controller animated:YES completion:nil];

Also implement the following UITextField delegate method in your Class

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

    NSString *finalString = [textField.text stringByReplacingCharactersInRange:range withString:string];
   [self.okAction setEnabled:(finalString.length >= 5)];
   return YES;
}

This should work

You can add an observer to your UITextField:

[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
    [textField addTarget:self action:@selector(alertControllerTextFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}

but first disable your button:

okAction.enabled = NO;

Then validate it in the method you specified :

- (void)alertTextFieldDidChange:(UITextField *)sender {
  UIAlertController *alertController = (UIAlertController *)self.presentedViewController;
  if (alertController) {
    UITextField *someTextField = alertController.textFields.firstObject;
    UIAlertAction *okAction = alertController.actions.lastObject;
    okAction.enabled = someTextField.text.length > 2;
  }
}

Swift 3 implementation based on soulshined's answer:

var someAlert: UIAlertController {
    let alert = UIAlertController(title: "Some Alert", message: nil, preferredStyle: .alert)

    alert.addTextField {
        $0.placeholder = "Write something"
        $0.addTarget(self, action: #selector(self.textFieldTextDidChange(_:)), for: .editingChanged)
    }

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

    let submitAction = UIAlertAction(title: "Submit", style: .default) { _ in
        // Do something...
    }

    submitAction.isEnabled = false
    alert.addAction(submitAction)
    return alert
}

func textFieldTextDidChange(_ textField: UITextField) {
    if let alert = presentedViewController as? UIAlertController,
        let action = alert.actions.last,
        let text = textField.text {
        action.isEnabled = text.characters.count > 0
    }
}

A better approach would be to alert the user about what is wrong with his input after validating his input, so that the user knows what the app is expecting from him.

- (void)askReasonWithPreviousReason:(NSString *)text
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Enter reason" preferredStyle:UIAlertControllerStyleAlert];

    [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField)
     {
         textField.text = text;
     }];

    [alertController addAction:[UIAlertAction actionWithTitle:@"Save" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
                                {
                                    if ([self isReasonValid:alertController.textFields.firstObject.text])
                                    {
                                        UIAlertController *alertController2 = [UIAlertController alertControllerWithTitle:AlertTitle message:@"Are you sure you would like to save?" preferredStyle:UIAlertControllerStyleAlert];

                                        [alertController2 addAction:[UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
                                                                     {
                                                                         [self saveReason:alertController.textFields.firstObject.text];
                                                                     }]];
                                        [alertController2 addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:Nil]];

                                        [self presentViewController:alertController2 animated:YES completion:nil];
                                    }
                                }]];

    [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:Nil]];

    [self presentViewController:alertController animated:YES completion:nil];
}

- (BOOL)isReasonValid:(NSString *)reason
{
    NSString *errorMessage = [[NSString alloc] init];

    if (reason.length < 5)
    {
        errorMessage = @"Reason must be more than 5 characters";
    }
    else if (reason.length > 100)
    {
        errorMessage = @"Reason must be less than 100 characters";
    }

    if (errorMessage.length != 0)
    {
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:errorMessage preferredStyle:UIAlertControllerStyleAlert];

        [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
                                    {
                                        [self askReasonWithPreviousReason:reason];
                                    }]];

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

        return NO;
    }

    return YES;
}

I had an answer for another post asking basically the same question on stackoverflow. To summarize, there are several ways to do this: use UITextFieldDelegate, Notification, KVO, or plainly add event handling target on the control. My solution is a simple UIAlertController subclass wrapped around the event handling target that you can configure simply by calling

    alert.addTextField(configurationHandler: { (textField) in
        textField.placeholder = "Your name"
        textField.autocapitalizationType = .words
    }) { (textField) in
        saveAction.isEnabled = (textField.text?.characters.count ?? 0) > 0
    }

This should be convenient if you have to deal with such alerts more than a few times in the project.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!