[Swift] How to properly subclass UITextfield and work with its delegate

Consider this:

class ViewController: UIViewController, UITextFieldDelegate  {
    var textfield: UITextField = {
        let tf = UITextField(frame: CGRect(x: 0, y: 0, width: 140, height: 30))
    }()

    override func viewDidLoad() {
        textfield.delegate = self
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        print("Inside textfield") 
    }
}


When I tap inside the textfield, textFieldDidBeginEditing() is called because the delegate handles that.

What happens if I want to subclass UITextField? How do I handle a tap event inside the subclassed textfield within the subclass? So for example:

class MyTextField: UITextField, UITextFieldDelegate {
    required override init(frame: CGRect) {
        self.delegate = self // CAN'T DO THIS!!!
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        print("Inside subclassed textfield")
        // This function is NOT executed when I tap inside this subclassed textfield!!
    }
}


The textFieldDidBeginEditing() within the subclass never gets called, I guess because the delegate is not properly set, and I don't know how to set it. It's not possible to do: self.delegate = self

Do I need to create a protocol for MyTextField? If so, how do I hook it all up? What would the code using MyTextField have to do? If I do:

    var subTF = MyTextField(....)
    subTF.delegate = self


Is that .delegate for class UITextField?? or is it for the subclass MyTextField?

Answered by ForumsContributor in

Your init is not correct.

You miss call to super.

    required override init(frame: CGRect) {
          super.init(frame: frame)
          delegate = self
    }

why do you add required ? What is the compiler error you get where // CAN'T DO THIS!!!

You should also need the init(coder):

     required init?(coder: NSCoder) {
          super.init(coder: coder)
          delegate = self
     }

With this, textFieldDidBeginEditing works as expected.

Accepted Answer

Thanks for feedback. Don't forget to close the thread.

As for your next question :

the ViewController code which uses MyTextField to also have a UITextFieldDelegate: 

class ViewController: UIViewController, UITextFieldDelegate { 
  override func viewDidLoad() { 
    let myTF = MyTextField( .... ) 
    myTF.delegate = self 
  } 

  func textFieldDidBeginEditing(_ textField: UITextField) {
    print("XXXXX"). // This is printed instead of "Inside subclassed textfield" within the subclass.  
} 

So, if the subclassed textfield's delegate is set to self within the calling code (ViewController in this case), the textFieldDidBeginEditing() inside the subclass is never called.

In general, is there a way to trigger textFieldDidBeginEditing() in both the calling code as well as the one inside the subclass?

Sequence happens as follows:

  • in viewDidLoad, all subviews are loaded.
  • hence the subclassed textfield's delegate is set to itself 
  • but then, you execute code in viewDidLoad and override the delegate to be the class (ViewController)
  • So only this one will be triggered

I do not know of direct mechanism to achieve what you want. And if that was possible, that could make debugging a bit hard.

What you could do:

  • remove the delegate declaration in ViewController for myTF
  • in the MyTextField subclass, post a new notification in textFieldDidBeginEditing
  • make ViewController class subscribe to this notification and handle it.

@Claude31 How do I "close the thread" for my question?

[Swift] How to properly subclass UITextfield and work with its delegate
 
 
Q