Search code examples
swiftxcodeuitextfielduialertcontroller

How do I observe user editing a textField in an UIAlertController?


I have an UIAlertController with a textField. Since I can't create an outlet for the textField I have to find another way to get ahold of a function that observes user input in realtime.

I have made some attempts, but not successfully. This thread explain how to add a target to the textField:

How do I check when a UITextField changes?

textfield.addTarget(self, action: #selector(ViewControllerr.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)

I tried this, but don't quite understand the #selector input. Does it want my UIViewController? or my UIAlertController I tried both but got the same error message:

Value of type 'UIViewController' has no member 'textFieldDidChange'

Same with UIAlertController.

I also tried setting my textField to delegate to access functions of that class:

textField.delegate = self as? UITextFieldDelegate

But I guess this isn't the correct approach as I still couldn't access any functions except by doing:

textField.delegate?.textFieldDidBeginEditing?(textField)

But that didn't give me anything either.

I also tried adding an extension like this:

extension UITextFieldDelegate {
    func textFieldDidBeginEditing(_ textField: UITextField) {
        print("🦋EDITING")
}// became first responder

    func textFieldDidEndEditing(_ textField: UITextField) {
        print("🦋EDITING")
    }
}

But for some reason I can't access them through textView

If I extend the class like this:

extension PickNumberViewController: UITextFieldDelegate {...}

I get the same error message

Value of type 'UITextField' has no member 'textFieldDel...'

which makes no sense since I set textField to UITextFieldDelegate not UITextField.

Let me know if you would like to see my code as well.


Solution

  • You can try to get a reference to it with self.textF = alert.textFields?[0]

    class ViewController: UIViewController {
    
        var textF:UITextField!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
    
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    
                //1. Create the alert controller.
                let alert = UIAlertController(title: "Some Title", message: "Enter a text", preferredStyle: .alert)
                alert.addTextField { (textField) in
                    textField.text = "Some default text"
                }
                 let tex = alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (_) in
    
                })) 
                // 4. Present the alert.
                self.present(alert, animated: true, completion: nil)
    
                self.textF =  alert.textFields?[0]
    
                self.textF.addTarget(self, action: #selector(self.textFieldDidChange), for: UIControl.Event.editingChanged)
    
            }
    
    
        }
    
        @objc func textFieldDidChange() {
            print(textF.text)
        }
    
    }