Can anyone tell me how to validate UITextFields
inside of a UIAlertController
?
I need it to prevent the user from clicking \"Save\" unless
First, you need to add some variables to your class:
private weak var saveAction : UIAlertAction?
private weak var textFieldName : UITextField?
private weak var textFieldEmail : UITextField?
private var validName = false
private var validEmail = false
Then, when you want to configure the alert controller (I only pasted the things that need to be changed):
alert.addTextFieldWithConfigurationHandler {
(textFieldName: UITextField!) in
textFieldName.placeholder = "Enter full name"
textFieldName.delegate = self
self.textFieldName = textFieldName
}
alert.addTextFieldWithConfigurationHandler {
(textFieldEmail: UITextField!) in
textFieldEmail.placeholder = "Enter valid email adress"
textFieldEmail.keyboardType = .EmailAddress
textFieldEmail.delegate = self
self.textFieldEmail = textFieldEmail
}
let saveAction = UIAlertAction(title: "Save",
style: .Default) { (action: UIAlertAction!) -> Void in
// here you are sure the name and email are correct
let name = (alert.textFields[0] as! UITextField).text
let email = (alert.textFields[1] as! UITextField).text
}
saveAction.enabled = false
self.saveAction = saveAction
Finally, you should implement this delegate method:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let newText = NSString(string: textField.text).stringByReplacingCharactersInRange(range, withString: string)
if textField == self.textFieldName {
// validate newText for the name requirements
validName = self.validateName(newText)
} else if textField == self.textFieldEmail {
// validate newText for the email requirements
validEmail = self.validateEmail(newText)
}
self.saveAction?.enabled = validEmail && validName
return true
}
I implemented a UIAlertController subclass which allows you to add a handler on text field changes when you add it to the alert:
public class TextEnabledAlertController: UIAlertController {
private var textFieldActions = [UITextField: ((UITextField)->Void)]()
func addTextField(configurationHandler: ((UITextField) -> Void)? = nil, textChangeAction:((UITextField)->Void)?) {
super.addTextField(configurationHandler: { (textField) in
configurationHandler?(textField)
if let textChangeAction = textChangeAction {
self.textFieldActions[textField] = textChangeAction
textField.addTarget(self, action: #selector(self.textFieldChanged), for: .editingChanged)
}
})
}
@objc private func textFieldChanged(sender: UITextField) {
if let textChangeAction = textFieldActions[sender] {
textChangeAction(sender)
}
}
}
So for your case the only extra thing that need to be added is to call the isValidEmail function in the textChangeAction handler:
alert.addTextField(configurationHandler: { (textField) in
// things you want to configure on the textfield
}) { (textField) in
saveAction.isEnabled = isValidEmail(textField.text ?? "")
}
This can be achieved via NSNotificationCenter before you display the alert controller, all you have to do is ask the notification center to observe the notification for UITextFieldTextDidChangeNotification and you should be good,
Given below is the implementation for the same
@IBAction func showAlert(sender: AnyObject) {
var alert = UIAlertController(title: "New user",
message: "Add a new user",
preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save",
style: .Default) { (action: UIAlertAction!) -> Void in
println("do your stuff here")
}
saveAction.enabled = false
let cancelAction = UIAlertAction(title: "Cancel",
style: .Default) { (action: UIAlertAction!) -> Void in
}
alert.addTextFieldWithConfigurationHandler {
(textFieldName: UITextField!) in
textFieldName.placeholder = "Enter full name"
}
alert.addTextFieldWithConfigurationHandler {
(textFieldEmail: UITextField!) in
textFieldEmail.placeholder = "Enter valid email adress"
textFieldEmail.keyboardType = .EmailAddress
}
// adding the notification observer here
NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[0],
queue: NSOperationQueue.mainQueue()) { (notification) -> Void in
let textFieldName = alert.textFields?[0] as! UITextField
let textFieldEmail = alert.textFields![1] as! UITextField
saveAction.enabled = self.isValidEmail(textFieldEmail.text) && !textFieldName.text.isEmpty
}
NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[1],
queue: NSOperationQueue.mainQueue()) { (notification) -> Void in
let textFieldEmail = alert.textFields?[1] as! UITextField
let textFieldName = alert.textFields?[0] as! UITextField
saveAction.enabled = self.isValidEmail(textFieldEmail.text) && !textFieldName.text.isEmpty
}
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert,
animated: true,
completion: nil)
}
// email validation code method
func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
if let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx) as NSPredicate? {
return emailTest.evaluateWithObject(testStr)
}
return false
}
You can use below code to validate TextFields in an UIAlertController :-
Step 1:
Declare "email_TF" to your viewcontroller.h
for example:
@property(strong,nonatomic)UITextField *email_TF;
Step 2:
UIAlertController *alert= [UIAlertController alertControllerWithTitle:@"Forgot Password?" message:nil preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler: ^(UITextField *textField){
textField.placeholder= @"Enter Your Valid Email";
textField.autocorrectionType= UITextAutocorrectionTypeYes;
textField.keyboardType= UIKeyboardTypeEmailAddress;
email_TF= textField;
}];
Step 3:
UIAlertAction *noButton= [UIAlertAction actionWithTitle:@"No, thanks" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action){
//Handel no, thanks button
}];
[alert addAction:noButton];
UIAlertAction *yesButton= [UIAlertAction actionWithTitle:@"Yes, please" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
//Handel your yes please button action here
NSLog(@"%@", email_TF.text);
if(email_TF.text.length>0){//
NSString *emailString= email_TF.text;
NSString *emailReg= @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest= [NSPredicate predicateWithFormat:@"SELF MATCHES %@",emailReg];
if(([emailTest evaluateWithObject:emailString]!=YES) || [emailString isEqualToString:@""]){
UIAlertView *loginalert= [[UIAlertView alloc] initWithTitle:@"Forgot Password !" message:@"\nPlease enter valid Email (example@example.com format) ." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
[loginalert show];
}else{
NSLog(@"your TextField successfully validated");
}
}else{
UIAlertView *alert= [[UIAlertView alloc] initWithTitle:@"Forgot Password !" message:@"\nPlease Enter Your Email..." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
}];
[alert addAction:yesButton];
Step 4:
[self presentViewController:alert animated:YES completion:nil];