Disable button in UIAlertView while text field is empty - ios

I make an AlertViewController with textField that asks user to type a name of new item for data model.
So I want to keep submit button disabled while text field is empty. In other case, when I create #IBOutlet in ViewController for textfield from storyboard I could just use some methods from UITextFieldDelegate protocol and solve problem without your help.
But now I can't.

Register for the text field change notifications and validate the text fields there:
#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
}

New Swift 4.2 Update
NotificationCenter.default.addObserver(
forName: UITextField.textDidChangeNotification,
object: alert.textFields?.first,
queue: .main) { (notification) -> Void in
guard let textFieldText = alert.textFields?.first?.text else { return }
saveAction.enabled = self.isValidEmail(textFieldText) && !textFieldText.isEmpty
}

add this code in viewDidLoad method
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(
self,
selector: "textFieldTextChanged:",
name:UITextFieldTextDidChangeNotification,
object: nil
)
and this method in ViewController
func textFieldTextChanged(sender : AnyObject) {
//your code
}

Related

How to disable UIAlertAction depending on UITextField?

I have an action that creates an alert when the button is tapped.
This alert consists of two textfields and two actions (add and dismiss).
Is there any simple way for me to disable the add button if the textfields are empty (I'll later check if the second one is really an URL but let's keep things focused on the action here)?
Here is my code and what I tried so far:
#IBAction func addSourceTapped(_ sender: Any) {
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
}
alert.addTextField { (textField) in
textField.placeholder = "Link"
}
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true
}
let action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = alert.textFields!.first!.text!
let link = alert.textFields!.last!.text!
if name != "" && link != "" {
alert.actions[0].isEnabled = true //doesn't do anything yet..
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
}
self.tableView.reloadData()
}
let action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
You should better use actions, it's simpler than the other answers. If you try to use delegate, methods didBeginEditing & didEndEditing will not handle it correctly. Neither do shouldChangeCharactersIn range, it performs before the input occurs in textfield, so it's not correct to check textField's text property there.
private var action: UIAlertAction!
#IBAction func addSourceTapped(_ sender: Any) {
////////
let alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged) // <---
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
/////
}
action.isEnabled = false
alert.addAction(action)
////////
}
#objc private func textFieldDidChange(_ field: UITextField) {
action.isEnabled = field.text?.count ?? 0 > 0
}
You can't write UITextField validating code (Code to enable/ disable Action) any where!!. This Validation must be done each time UItextfield update. So for doing that you need to get the delegate from UITextField for its updates
You need to save the textfield globally and assign delegate of textfields to your ViewController. By doing that you can code for validating code for textfields in your UIViewController and programmatically Enable or disable your actions
class YOUR_CLASS_NAME:UIViewController,UITextFieldDelegate {
var alert: UIAlertController!
var action: UIAlertAction!
var action2: UIAlertAction!
var nameTextFeld:UITextField!
var linkTextFeld:UITextField!
#IBAction func addSourceTapped(_ sender: Any) {
alert = UIAlertController(title: "Add a News Source", message: nil, preferredStyle: .alert)
alert.addTextField { (textField) in
self.nameTextFeld = textField
self.nameTextFeld.placeholder = "Name"
self.nameTextFeld.delegate = self
}
alert.addTextField { (textField) in
self.linkTextFeld = textField
self.linkTextFeld.placeholder = "Link"
self.linkTextFeld.delegate = self
}
action = UIAlertAction(title: "Add", style: .default) { (_) in
let name = self.alert.textFields!.first!.text!
let link = self.alert.textFields!.last!.text!
if CoreDataHandler.saveSource(name: "\(name)", link: "\(link)") {
for _ in CoreDataHandler.fetchSource()! {
}
}
self.tableView.reloadData()
}
action.isEnabled = false
action2 = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(action)
alert.actions[0].isEnabled = false
alert.addAction(action2)
present(alert, animated: true, completion: nil)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if !((nameTextFeld.text?.isEmpty)! && (linkTextFeld.text?.isEmpty)!) {
action.isEnabled = true
}
return true
}
}
Do that by configuring the text field when adding it
alert.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = "Name"
// Other configuration such as textField.autocapitalizationType = .words
NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in
let nameField = alert.textFields![0] as UITextField
let linkField = alert.textFields![1] as UITextField
action.isEnabled = self.getTextFieldContent(nameField) != "" && self.getTextFieldContent(linkField) != ""
}
})
You need to do this separately for both text fields (though you could do that by reusing the same code). Note also, that if you reference the textfields directly in the action's handler block, it will create a strong reference cycle and your controller will not be deinited. To avoid that do the reference to the text field with a local nullable variable like this
var tf: UITextField?
let action = UIAlertAction(title: "Add", style: .default) { (_) in
guard let textField = tf else {
return;
}
let name = textField.text!
// Rest the action here
}
alertController.addTextField { (textField) in
// Configure textField here
tf = textField
}
Programmatic solution with the usage of the actions.
Add button to class and continue to change its status according to the change made in the text field.
import UIKit
final class ViewWithConfirmationController: UIViewController {
private let askButton = UIButton()
private let deleteAction = UIAlertAction(
title: "Confirm",
style: .default
) { _ in
// Confirmed
}
init() {
super.init(nibName: nil, bundle: nil)
view.addSubview(askButton)
askButton.setTitle("Call alert", for: .normal)
askButton.addTarget(
self,
action: #selector(callAlert),
for: .touchUpInside
)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc func callAlert() {
let alert = UIAlertController(
title: "Confirmation alert",
message: """
Do you really want to do that?
Please type in the magic word to confirm.
""",
preferredStyle: .alert
)
alert.addTextField { textField in
textField.placeholder = "Magic word"
textField.addTarget(
self,
action: #selector(self.textFieldDidChange(_:)),
for: .editingChanged
)
}
alert.addAction(
UIAlertAction(
title: "Cancel",
style: .cancel,
handler: { _ in }
))
alert.addAction(deleteAction)
// Confirm button will disabled until user type current organisation name
deleteAction.isEnabled = false
present(alert, animated: true, completion: nil)
}
#objc private func textFieldDidChange(_ field: UITextField) {
guard let text = field.text else {
print("Can't get text from text field in \(#function)")
return
}
deleteAction.isEnabled = !text.isEmpty
}
}

Swift 4. How can I make method return bool from Firebase completion handler

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "ChosenCell" {
if let indexPath = tableView.indexPath(for: sender as! UITableViewCell) {
reference.child("List").child(storyArray[indexPath.row].name).observeSingleEvent(of: .childAdded) { snapshot in
let snapshotValue = snapshot.value as! Dictionary<String,String>
if snapshotValue["Creator"]! != self.currentUser!.email! {
//return false
//continue
} else {
let alert = UIAlertController(title: "Warning", message: "Enter password:", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default) { alertAction in
let textField = alert.textFields![0] as UITextField
if textField.text! != snapshotValue["Password"]! {
//return false
}
}
alert.addTextField { textField in
textField.placeholder = "password"
}
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
}
}
}
return true
}
When user choose cell if user is currentUser or if there is no password "ChosenCell" segue should perform.
Else alert: "Please enter password". And if the password is right "ChosenCell" segue should perform.
How can I do this?
In this case func shouldPerformSegue always returns true, because observeSingleEvent performs in background thread and shouldPerformSegue doesn't wait for completion of observeSingleEvent.
You should implement logic in this way:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let name = storyArray[indexPath.row].name
reference.child("List").child(name).observeSingleEvent(of: .childAdded) { snapshot in
let snapshotValue = snapshot.value as! [String : String]
if snapshotValue["Creator"]! == self.currentUser!.email! { // user is the creator of this cell, so perform segue
performSegue(withIdentifier: "ChosenCell", sender: nil)
} else { // user is not the creator of this cell
let alert = UIAlertController(title: "Warning", message: "Enter password:", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default) { alertAction in
let textField = alert.textFields!.first
if textField.text! != snapshotValue["Password"]! { // wrong password
// show error message
} else { // right password
performSegue(withIdentifier: "ChosenCell", sender: nil)
}
}
alert.addTextField { textField in
textField.placeholder = "password"
}
alert.addAction(action)
present(alert, animated: true)
}
}
}

Swift iOS How to display an alert message from the handler of another alert message

I'm trying to implement a forgot password feature in my app so users can enter their email in and have it reset in the database and have the new generated password emailed to them.
I believe my code should work once I fix a few minor issues but the main hurdle I'm having is how to display an alert message from the handler of another alert message.
Any idea how to do it? Either the alert message doesn't show up at all or the first one doesn't close at all.
Here is my attempt at it:
//This function will send a password reset email
func emailPassword(alertAction: UIAlertAction!) -> Void {
let textField = reset_alert.textFields![0] as UITextField
if(!textField.text!.isEmpty){
if(textField != "mik"){
let query = PFQuery(className: "_User")
let forgotten_email = textField.text
query.whereKey("email", equalTo: forgotten_email!)
query.findObjectsInBackgroundWithBlock{
(objects: [PFObject]?, error: NSError?) -> Void in
//NO ERROR//
if(error == nil){
//email in db generate random password
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomString : NSMutableString = NSMutableString(capacity: 12)
var users_name = ""
for _ in 0...10{
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
//set new password for user
if let objects = objects {
for object in objects {
object["_hashed_password"] = randomString
users_name = object["name"] as! String
//send password to email
self.mailgun.sendMessageTo("\(users_name) <\(textField)>", from: "")
self.displayAlert("SUCCESS", msg: "Check your email for your new password")
self.reset_alert.dismissViewControllerAnimated(true, completion: nil)
}
}
else{
self.reset_alert.dismissViewControllerAnimated(true, completion: nil)
self.displayAlert("ERROR", msg: "Email not registered to an account")
}
}
//ERROR//
else{
self.reset_alert.dismissViewControllerAnimated(true, completion: nil)
self.displayAlert("ERROR", msg: "Email not registered to an account") }
} //end if textfield not admin email
self.presentViewController(reset_alert, animated: true, completion: nil)
}
}//end of if textfield is empty
}
Try this extension:
typealias AlertActionBlock = (UIAlertAction) -> Void
extension UIViewController {
func flash(title title:String?, message:String?, cancelTitle:String?, actions:UIAlertAction?...) {
let b = {
let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let cancelBlock:AlertActionBlock = {(action:UIAlertAction) -> Void in }
let cancelAction = UIAlertAction(title: cancelTitle, style: UIAlertActionStyle.Cancel, handler: cancelBlock)
alertController.addAction(cancelAction)
for action in actions {if let action = action {alertController.addAction(action)}}
self.presentViewController(alertController, animated: true, completion: nil)
}
if NSThread.isMainThread() {
b()
} else {
dispatch_async(dispatch_get_main_queue(), b)
}
}
}
That should let you call that function from background threads or the main thread just call that function and fill in the variables
EDIT (I didn't realize you need a textfield) so try this:
func flash(title title:String?, message:String?, textFieldConfigurator:(UITextField -> Void)? = nil, cancelTitle:String?, actions:UIAlertAction?...) {
let b = { () -> Void in
let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
if let textFieldConfigurator = textFieldConfigurator {alertController.addTextFieldWithConfigurationHandler(textFieldConfigurator)}
let cancelBlock:AlertActionBlock = {(action:UIAlertAction) -> Void in }
let cancelAction = UIAlertAction(title: cancelTitle, style: UIAlertActionStyle.Cancel, handler: cancelBlock)
alertController.addAction(cancelAction)
for action in actions {if let action = action {alertController.addAction(action)}}
self.presentViewController(alertController, animated: true, completion: nil)
}
if NSThread.isMainThread() {
b()
} else {
dispatch_async(dispatch_get_main_queue(), b)
}
}
If you need multiple text fields make it an array and iterate through it. Let me know how it goes!

Make alert with action button - Swift

I have alert, that write to iOS 8+, I must write same alert to the iOS 7.0 (I'm use four alert's with other request)
There are my code:
func AlertForNumber () {
var alertController: UIAlertController?
//
alertController = UIAlertController(title: "First", message: "Enter number", preferredStyle: .Alert)
alertController!.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.text = "38"
})
let action = UIAlertAction(title: "Next", style: UIAlertActionStyle.Default, handler: {[weak self]
(paramAction: UIAlertAction!) in
if let textFields = alertController?.textFields {
let textFields = textFields as! [UITextField]
let enterText = textFields[0].text
if (count(enterText) < 12){
self?.ErrorForNumber()
} else {
self!.data.numberID = enterText
self!.data.SaveData(enterText, codetext: self!.data.codeID)
self!.json.UfR()
}
}
})
alertController?.addAction(action)
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(alertController!, animated: true, completion: nil)
})
}
At that alert I must input my number, and send to the server.
I must use only alert with text field
After I must input code at next alert:
func AlertForCode () {
var alertController: UIAlertController?
alertController = UIAlertController(title: "Second", message: "Enter code", preferredStyle: .Alert)
alertController!.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.placeholder = code_text
})
let action = UIAlertAction(title: "Next", style: UIAlertActionStyle.Default, handler: {[weak self]
(paramAction: UIAlertAction!) in
if let textFields = alertController?.textFields {
let textFields = textFields as! [UITextField]
let enterText = textFields[0].text
self!.data.codeID = enterText
self!.data.SaveData(self!.data.numberID, codetext: enterText)
self!.json.UfR()
}
})
alertController?.addAction(action)
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(alertController!, animated: true, completion: nil)
})
}
So that I must write to the iOS 7.0
func AlertForNumber () {
let alertView = UIAlertView(title: "First", message: "Enter number", delegate: self, cancelButtonTitle: "Next")
alertView.alertViewStyle = UIAlertViewStyle.PlainTextInput
alertView.textFieldAtIndex(0)?.text = "38"
alertView.show()
}
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
println("next")
let enterText = alertView.textFieldAtIndex(0)!.text
if (count(enterText) < 12){
self?.ErrorForNumber()
} else {
self!.data.numberID = enterText
self!.data.SaveData(enterText, codetext: self!.data.codeID)
self!.json.UfR()
}
}

Check on UIAlertController TextField for enabling the button

I have an AlertController with a text field and two button: CANCEL and SAVE. This is the code:
#IBAction func addTherapy(sender: AnyObject)
{
let addAlertView = UIAlertController(title: "New Prescription", message: "Insert a name for this prescription", preferredStyle: UIAlertControllerStyle.Alert)
addAlertView.addAction(UIAlertAction(title: "Cancel",
style: UIAlertActionStyle.Default,
handler: nil))
addAlertView.addAction(UIAlertAction(title: "Save",
style: UIAlertActionStyle.Default,
handler: nil))
addAlertView.addTextFieldWithConfigurationHandler({textField in textField.placeholder = "Title"})
self.presentViewController(addAlertView, animated: true, completion: nil)
}
What I want to do is implement a check on the textfield for disabling the SAVE button when the textfield is empty just like Pictures Application of iOS when you want create a NewAlbum. Please someone can explain me what to do?
There is a much simpler way without using notification center, in swift:
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.addTextField(configurationHandler: {(textField: UITextField) in
textField.placeholder = placeholderStr
textField.addTarget(self, action: #selector(self.textChanged(_:)), for: .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.isEnabled = false
self.present(alert, animated: true, completion: nil)
}
func textChanged(_ sender:UITextField) {
self.actionToEnable?.isEnabled = (sender.text! == "Validation")
}
I would first create the alertcontroller with the save action initially disabled. Then when adding the textfield inculde a Notification to observe its change in the handler and in that selector just toggle the save actions enabled property.
Here is what I am saying:
//hold this reference in your class
weak var AddAlertSaveAction: UIAlertAction?
#IBAction func addTherapy(sender : AnyObject) {
//set up the alertcontroller
let title = NSLocalizedString("New Prescription", comment: "")
let message = NSLocalizedString("Insert a name for this prescription.", comment: "")
let cancelButtonTitle = NSLocalizedString("Cancel", comment: "")
let otherButtonTitle = NSLocalizedString("Save", comment: "")
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
// Add the text field with handler
alertController.addTextFieldWithConfigurationHandler { textField in
//listen for changes
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleTextFieldTextDidChangeNotification:", name: UITextFieldTextDidChangeNotification, object: textField)
}
func removeTextFieldObserver() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: alertController.textFields[0])
}
// Create the actions.
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel) { action in
NSLog("Cancel Button Pressed")
removeTextFieldObserver()
}
let otherAction = UIAlertAction(title: otherButtonTitle, style: .Default) { action in
NSLog("Save Button Pressed")
removeTextFieldObserver()
}
// disable the 'save' button (otherAction) initially
otherAction.enabled = false
// save the other action to toggle the enabled/disabled state when the text changed.
AddAlertSaveAction = otherAction
// Add the actions.
alertController.addAction(cancelAction)
alertController.addAction(otherAction)
presentViewController(alertController, animated: true, completion: nil)
}
//handler
func handleTextFieldTextDidChangeNotification(notification: NSNotification) {
let textField = notification.object as UITextField
// Enforce a minimum length of >= 1 for secure text alerts.
AddAlertSaveAction!.enabled = textField.text.utf16count >= 1
}
I am doing this in another project - I got this pattern directly from apple examples. They have a very good example project outlining a few of these patterns in the UICatalog examples: https://developer.apple.com/library/content/samplecode/UICatalog/Introduction/Intro.html
Swift 3.0 Updated Solution given By #spoek
func showAlert()
{
let titleStr = "title"
let messageStr = "message"
let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.alert)
let placeholderStr = "placeholder"
alert.addTextField(configurationHandler: {(textField: UITextField) in
textField.placeholder = placeholderStr
textField.addTarget(self, action: #selector(self.textChanged(_:)), for: .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.isEnabled = false
self.present(alert, animated: true, completion: nil)
}
func textChanged(_ sender:UITextField) {
self.actionToEnable?.isEnabled = (sender.text! == "Validation")
}
I implemented a subclass of UIAlertController for conveniently adding text fields and associated enabling and disabling of buttons. The basic logic is similar to that Sourabh Sharma but everything is encapsulated in this subclass for tidiness. This should be helpful if your project involves a lot of such alert functionalities.
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)
}
}
}
To use it, just provide a textChangeAction block when adding the text fields:
alert.addTextField(configurationHandler: { (textField) in
textField.placeholder = "Your name"
textField.autocapitalizationType = .words
}) { (textField) in
saveAction.isEnabled = (textField.text?.characters.count ?? 0) > 0
}
For the full example, see the git page.

Resources