2014-09-02 2 views
36

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

ответ

56

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

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

Вот пример. Мы создали текстовое поле, как это:

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

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

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

Впоследствии пользователь не может нажмите OK, если нет какой-то фактический текст в текстовом поле:

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 != "") 
} 
+0

Полный пример здесь: HTTPS : // GitHub.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch13p620dialogsOniPhone/ch26p888dialogsOniPhone/ViewController.swift – matt

+0

супер !!! Многие благодарны –

+0

Есть ли пример Objective-C этой прокладки? – Adrian

6

списывание прочь @ ответ Мэтта, вот как я сделал то же самое в 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); 
} 
8

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

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") 
} 
+0

Спасибо человеку! Работает как шарм! –

0

Я понимаю, что это в 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]; 
Смежные вопросы