仅在验证输入后启用 UIAlertController 的 UIAlertAction
Posted
技术标签:
【中文标题】仅在验证输入后启用 UIAlertController 的 UIAlertAction【英文标题】:Enable UIAlertAction of UIAlertController only after input is validated 【发布时间】:2015-08-30 16:22:02 【问题描述】:我正在使用UIAlertController
显示一个对话框,其中包含一个UITextField
和一个标记为“Ok”的UIAlertAction
按钮。如何在UITextField
中输入多个字符(比如 5 个字符)之前禁用该按钮?
【问题讨论】:
你需要检查 UITextField 长度 .. 如果 UITextField 长度为 5 则按钮将启用其他方式不 【参考方案1】:您可以将观察者添加到您的UITextField
:
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField)
[textField addTarget:self action:@selector(alertControllerTextFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
但首先禁用您的按钮:
okAction.enabled = NO;
然后在你指定的方法中验证它:
- (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;
【讨论】:
【参考方案2】:在头文件中添加以下属性
@property(nonatomic, strong)UIAlertAction *okAction;
然后在ViewController
的viewDidLoad
方法中复制以下代码
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];
还在你的类中实现以下 UITextField
委托方法
- (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;
这应该可以工作
【讨论】:
您可能还想添加:- (BOOL) textFieldShouldClear:(UITextField *)textField [self.okAction setEnabled:NO]; return YES;
【参考方案3】:
基于 soulshined 的回答的 Swift 3 实现:
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
【讨论】:
你应该在.addTextField(configurationHandler
里面设置textField.delegate = self
【参考方案4】:
借助 Swift 5.3 和 ios 14,您可以使用组合框架和 NotificationCenter
来跟踪给定 UITextField
的 UITextField.textDidChangeNotification
通知。
以下代码显示了一个可能的实现,以便根据textField
的字符数启用UIAlertController
的按钮:
import UIKit
import Combine
class ViewController: UIViewController
var cancellable: AnyCancellable?
override func viewDidLoad()
super.viewDidLoad()
view.backgroundColor = .systemBackground
let action = UIAction(
title: "Change title",
handler: [unowned self] _ in
self.presentAlert()
)
let barButtonItem = UIBarButtonItem(primaryAction: action)
navigationItem.rightBarButtonItem = barButtonItem
extension ViewController
func presentAlert()
let alertController = UIAlertController(
title: "Change title",
message: nil,
preferredStyle: .alert
)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) _ in
print("Cancelled")
let renameAction = UIAlertAction(
title: "Rename",
style: .default
) [unowned alertController] action in
print("Renamed: \(alertController.textFields!.first!.text!)")
renameAction.isEnabled = false
alertController.addAction(cancelAction)
alertController.addAction(renameAction)
alertController.addTextField(configurationHandler: textField in
self.cancellable = NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification, object: textField)
.sink(receiveValue: _ in
let textCount = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines).count ?? 0
renameAction.isEnabled = textCount >= 5 // min 5 characters
)
)
present(alertController, animated: true)
【讨论】:
【参考方案5】:更好的方法是在验证用户的输入后提醒用户他的输入有什么问题,以便用户知道应用对他的期望。
- (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;
【讨论】:
【参考方案6】:我有 an answer 的另一篇帖子在 *** 上提出了基本相同的问题。总而言之,有几种方法可以做到这一点:使用 UITextFieldDelegate、Notification、KVO,或者在控件上简单地添加事件处理目标。我的解决方案是 a simple UIAlertController subclass 包裹在事件处理目标周围,您可以通过调用简单地配置
alert.addTextField(configurationHandler: (textField) in
textField.placeholder = "Your name"
textField.autocapitalizationType = .words
) (textField) in
saveAction.isEnabled = (textField.text?.characters.count ?? 0) > 0
如果您必须在项目中多次处理此类警报,这应该很方便。
【讨论】:
以上是关于仅在验证输入后启用 UIAlertController 的 UIAlertAction的主要内容,如果未能解决你的问题,请参考以下文章