ฉันกำลังเพิ่ม UITextField
ไปที่ UIAlertController
ซึ่งปรากฏเป็น AlertView
ก่อนที่จะยกเลิก UIAlertController
ฉันต้องการตรวจสอบอินพุตของ UITextField
จากการตรวจสอบความถูกต้อง ฉันต้องการยกเลิก UIAlertController
หรือไม่ แต่ฉันไม่รู้ว่าจะป้องกันการยกเลิกการทำงานของ UIAlertController
ได้อย่างไรเมื่อกดปุ่ม มีใครแก้ไขปัญหานี้หรือความคิดใด ๆ ที่จะเริ่มต้น? ฉันไปที่ Google แต่โชคไม่ดี :/ ขอบคุณ!
ป้องกันการเลิกจ้าง UIAlertController
คำตอบ (5)
คุณพูดถูก: หากผู้ใช้สามารถแตะปุ่มในการแจ้งเตือนของคุณได้ การแจ้งเตือนนั้นก็จะถูกยกเลิก ดังนั้นคุณต้องการป้องกันไม่ให้ผู้ใช้แตะปุ่ม! ทั้งหมดนี้เป็นเพียงเรื่องของการปิดใช้ปุ่ม UIAlertAction ของคุณ หากปิดใช้การแจ้งเตือน ผู้ใช้จะไม่สามารถแตะเพื่อปิดได้
หากต้องการรวมสิ่งนี้เข้ากับการตรวจสอบฟิลด์ข้อความ ให้ใช้วิธีการมอบหมายฟิลด์ข้อความหรือวิธีการดำเนินการ (กำหนดค่าไว้ในตัวจัดการการกำหนดค่าของฟิลด์ข้อความเมื่อคุณสร้างขึ้น) เพื่อเปิด/ปิดใช้งาน UIAlertActions อย่างเหมาะสม ขึ้นอยู่กับข้อความที่ป้อน (หรือยังไม่ได้) .
นี่คือตัวอย่าง เราสร้างช่องข้อความดังนี้:
alert.addTextFieldWithConfigurationHandler {
(tf:UITextField!) in
tf.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged)
}
เรามีการดำเนินการยกเลิกและการดำเนินการตกลง และเรานำการดำเนินการตกลงมาสู่โลกที่ปิดใช้งาน:
(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 != "")
}
แก้ไข นี่คือโค้ดด้านบนเวอร์ชันปัจจุบัน (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 != "")
}
ฉันได้ทำให้คำตอบของ Matt ง่ายขึ้นโดยไม่ต้องข้ามลำดับชั้นของมุมมอง นี่เป็นการถือว่าการกระทำนั้นเป็นตัวแปรที่อ่อนแอแทน นี่คือตัวอย่างการทำงานที่สมบูรณ์:
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 แต่มันแสดงหลักการ ฉันจะอัปเดตสิ่งนี้ด้วยเวอร์ชันที่รวดเร็วในภายหลัง
คุณสามารถทำเช่นเดียวกันโดยใช้บล็อกเป็นเป้าหมาย
เพิ่มคุณสมบัติให้กับ 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];
นี่เป็นแนวคิดเดียวกันกับคำตอบอื่น ๆ แต่ฉันต้องการวิธีการง่าย ๆ ที่แยกได้ในส่วนขยายและพร้อมใช้งานในคลาสย่อย UIViewController ใด ๆ มันแสดงการแจ้งเตือนพร้อมช่องป้อนข้อความหนึ่งช่องและปุ่มสองปุ่ม: ตกลงและยกเลิก
extension UIViewController {
func askForTextAndConfirmWithAlert(title: String, placeholder: String, okHandler: @escaping (String?)->Void) {
let alertController = UIAlertController(title: title, message: nil, preferredStyle: .alert)
let textChangeHandler = TextFieldTextChangeHandler { text in
alertController.actions.first?.isEnabled = !(text ?? "").isEmpty
}
var textHandlerKey = 0
objc_setAssociatedObject(self, &textHandlerKey, textChangeHandler, .OBJC_ASSOCIATION_RETAIN)
alertController.addTextField { textField in
textField.placeholder = placeholder
textField.clearButtonMode = .whileEditing
textField.borderStyle = .none
textField.addTarget(textChangeHandler, action: #selector(TextFieldTextChangeHandler.onTextChanged(sender:)), for: .editingChanged)
}
let okAction = UIAlertAction(title: CommonLocStr.ok, style: .default, handler: { _ in
guard let text = alertController.textFields?.first?.text else {
return
}
okHandler(text)
objc_setAssociatedObject(self, &textHandlerKey, nil, .OBJC_ASSOCIATION_RETAIN)
})
okAction.isEnabled = false
alertController.addAction(okAction)
alertController.addAction(UIAlertAction(title: CommonLocStr.cancel, style: .cancel, handler: { _ in
objc_setAssociatedObject(self, &textHandlerKey, nil, .OBJC_ASSOCIATION_RETAIN)
}))
present(alertController, animated: true, completion: nil)
}
}
class TextFieldTextChangeHandler {
let handler: (String?)->Void
init(handler: @escaping (String?)->Void) {
self.handler = handler
}
@objc func onTextChanged(sender: AnyObject) {
handler((sender as? UITextField)?.text)
}
}