UITextField
として表示されるUIAlertController
にAlertView
を追加しています。 UIAlertController
を閉じる前に、UITextField
の入力を検証します。検証に基づいて、UIAlertController
を却下するかどうかを決めます。しかし、ボタンが押されたときにUIAlertController
の却下アクションを防ぐ方法がわかりません。誰もこの問題やどこからアイデアを解決しましたか?私はグーグルに行きましたが、運がありません:/ありがとう!
正しい:ユーザーがアラートのボタンをタップできる場合、アラートは消えます。そのため、ユーザーがボタンをタップできないようにする必要があります。 UIAlertActionボタンを無効にするだけです。アラートアクションが無効になっている場合、ユーザーはそれをタップして閉じることはできません。
これをテキストフィールドの検証と組み合わせるには、テキストフィールドのデリゲートメソッドまたはアクションメソッド(作成時にテキストフィールドの構成ハンドラーで構成)を使用して、入力されたテキスト(または入力されていない)に応じてUIAlertActionsを適切に有効/無効にします。
以下に例を示します。次のようなテキストフィールドを作成しました。
alert.addTextFieldWithConfigurationHandler {
(tf:UITextField!) in
tf.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged)
}
キャンセルアクションとOKアクションがあり、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
そして
@objc 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 != "")
}
ビュー階層を移動することなく、マットの答えを単純化しました。これは、代わりにアクション自体を弱い変数として保持しています。これは完全に機能する例です。
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")
}
@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);
}
これはObjectiv-Cにあることを理解していますが、プリンシパルを示しています。 Swiftバージョンで後で更新します。
ブロックをターゲットとして使用して同じことを行うこともできます。
ViewController
にプロパティを追加して、ブロック(Swiftのクロージャー)が強力な参照を持つようにします
@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];