Подтвердить что ты не робот

Запретить увольнение UIAlertController

Я добавляю UITextField к UIAlertController, который отображается как AlertView. Прежде чем отклонить UIAlertController, я хочу проверить ввод UITextField. На основании проверки я хочу отклонить UIAlertController или нет. Но я не знаю, как предотвратить отклонение действия UIAlertController при нажатии кнопки. Кто-нибудь решил эту проблему или какие-то идеи, с чего начать? Я пошел в Google, но не повезло:/Спасибо!

4b9b3361

Ответ 1

Вы правы: если пользователь может нажать кнопку в вашем предупреждении, предупреждение будет отклонено. Поэтому вы хотите, чтобы пользователь не нажал кнопку! Все дело в том, чтобы отключить кнопки UIAlertAction. Если действие предупреждения отключено, пользователь не может нажать на него, чтобы уволить.

Чтобы объединить это с проверкой текстового поля, используйте метод делегирования текстового поля или метод действия (настроенный в обработчике конфигурации текстового поля при его создании), чтобы включить/отключить UIAlertActions соответствующим образом в зависимости от того, какой текст (или не имеет).

Вот пример. Мы создали текстовое поле следующим образом:

alert.addTextFieldWithConfigurationHandler {
    (tf:UITextField!) in
    tf.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged)
}

У нас есть действие "Отмена" и действие "ОК", и мы внесли действие OK в мир отключен:

(alert.actions[1] as UIAlertAction).enabled = false

Впоследствии пользователь не может нажать "ОК", если в текстовом поле нет определенного текста:

func textChanged(sender:AnyObject) {
    let tf = sender as UITextField
    var resp : UIResponder = tf
    while !(resp is UIAlertController) { resp = resp.nextResponder() }
    let alert = resp as UIAlertController
    (alert.actions[1] as UIAlertAction).enabled = (tf.text != "")
}

EDIT Здесь текущая версия (Swift 3.0.1) приведенного выше кода:

alert.addTextField { tf in
    tf.addTarget(self, action: #selector(self.textChanged), for: .editingChanged)
}

и

alert.actions[1].isEnabled = false

и

func textChanged(_ sender: Any) {
    let tf = sender as! UITextField
    var resp : UIResponder! = tf
    while !(resp is UIAlertController) { resp = resp.next }
    let alert = resp as! UIAlertController
    alert.actions[1].isEnabled = (tf.text != "")
}

Ответ 2

Я упростил матовый ответ без просмотра иерархического представления. Вместо этого это действие выполняется как слабая переменная. Это полностью рабочий пример:

weak var actionToEnable : UIAlertAction?

func showAlert()
{
    let titleStr = "title"
    let messageStr = "message"

    let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.Alert)

    let placeholderStr =  "placeholder"

    alert.addTextFieldWithConfigurationHandler({(textField: UITextField) in
        textField.placeholder = placeholderStr
        textField.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged)
    })

    let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: { (_) -> Void in

    })

    let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: { (_) -> Void in
        let textfield = alert.textFields!.first!

        //Do what you want with the textfield!
    })

    alert.addAction(cancel)
    alert.addAction(action)

    self.actionToEnable = action
    action.enabled = false
    self.presentViewController(alert, animated: true, completion: nil)
}

func textChanged(sender:UITextField) {
    self.actionToEnable?.enabled = (sender.text! == "Validation")
}

Ответ 3

Отказ от ответа @Matt, вот как я сделал то же самое в Obj-C

- (BOOL)textField: (UITextField*) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString*)string
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange: range withString: string];

    // check string length
    NSInteger newLength = [newString length];
    BOOL okToChange = (newLength <= 16);    // don't allow names longer than this

    if (okToChange)
    {
        // Find our Ok button
        UIResponder *responder = textField;
        Class uiacClass = [UIAlertController class];
        while (![responder isKindOfClass: uiacClass])
        {
            responder = [responder nextResponder];
        }
        UIAlertController *alert = (UIAlertController*) responder;
        UIAlertAction *okAction  = [alert.actions objectAtIndex: 0];

        // Dis/enable Ok button based on same-name
        BOOL duplicateName = NO;
        // <check for duplicates, here>

        okAction.enabled = !duplicateName;
    }


    return (okToChange);
}

Ответ 4

Я понимаю, что это в Objectiv-C, но в нем показан принцип. Я обновлю это с быстрой версией позже.

Вы также можете сделать то же самое, используя блок в качестве цели.

Добавьте свойство к вашему ViewController, чтобы блок (закрытие для быстрого) имел сильную ссылку

@property (strong, nonatomic) id textValidationBlock;

Затем создайте AlertViewController так:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

}];

   __weak typeof(self) weakSelf = self;
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [weakSelf doSomething];

}];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[alertController.actions lastObject].enabled = NO;
self.textValidationBlock = [^{
    UITextField *textField = [alertController.textFields firstObject];
    if (something) {
        alertController.message = @"Warning message";
        [alertController.actions lastObject].enabled = NO;
    } else if (somethingElse) {
        alertController.message = @"Another warning message";
        [alertController.actions lastObject].enabled = NO;
    } else {
        //Validation passed
        alertController.message = @"";
        [alertController.actions lastObject].enabled = YES;
    }

} copy];
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
    textField.placeholder = @"placeholder here";
    [textField addTarget:weakSelf.textValidationBlock action:@selector(invoke) forControlEvents:UIControlEventEditingChanged];
}];
[self presentViewController:alertController animated:YES completion:nil];