1

I have a UITextField subclass. I needed to know when text did change and I was able to get that with NotificationCenter and observing .UITextFieldTextDidChange but now I need to know when the user tap return button. The only solution that I can think about it is setting the UITextField subclass to be the delegate of it self, but it sound not clean.

  1. Is there a clean way to get the return key event from subclass
  2. Is it Ok to to set the UITextField subclass to be the delegate of it self ?
iOSGeek
  • 5,115
  • 9
  • 46
  • 74
  • May I ask you why you need that? – Andrea Oct 16 '17 at 14:01
  • I'm currently using the 'UITextFieldDelegate' where I'm setting the delegate to the appropriate textField(s), where the RETURN button needs to be identified. You can then identify with 'func textFieldShouldReturn(_ textField: UITextField) -> Bool' if the return button was tapped. Nevertheless, I'm not 100% sure if this is the cleanest solution. – AlexWoe89 Oct 16 '17 at 14:09
  • There is an interesting discussion of the second point of your question here: https://stackoverflow.com/questions/29054602/does-a-class-being-its-own-delegate-follow-ios-convention – Craig Grummitt Oct 16 '17 at 16:08
  • @Andrea Trying to make the textField adapted to be used as search text field, I ended up putting the textField in a UIView and make that view the delegate the good thing about that is that I can hide the textfield (`private`) and expose what is only needed – iOSGeek Oct 17 '17 at 08:16

3 Answers3

2

In your subclass do

self.addTarget(self, action: #selector(returnKeyPressed), for: .editingDidEndOnExit);

Looking at Apples doc you see UIControlEvents

UIControlEventEditingDidEndOnExit = 1 << 19, // 'return key' ending editing

Ladislav
  • 7,223
  • 5
  • 27
  • 31
  • Good to know. That answer the question. But I ended up wrapping the textField in a `UIView` and make it the delegate of `UITextField` which can be `private` – iOSGeek Oct 17 '17 at 08:18
1

Simply duplicate UITextFieldDelegate with a new protocol and pass the calls from UITextFieldDelegate through the custom delegate to the view controller.

First, create a new protocol with whichever delegate methods you want to pass through to the view controller.

protocol CustomTextFieldDelegate {
    func textFieldDidChangeSelection(_ textField: UITextField)
}

Then, set the delegate of the subclass to self, and whenever those methods are called (within the subclass), do what you need with them and then pass them along to the custom delegate.

class CustomTextField: UITextField {
    var customDelegate: CustomTextFieldDelegate?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        delegate = self
    }
    
    required init?(coder: NSCoder) {
        return nil
    }
}

extension CustomTextField: UITextFieldDelegate {
    func textFieldDidChangeSelection(_ textField: UITextField) {

        // Do what you need in the subclass.

        // When done, pass the call along to the custom delegate.
        customDelegate?.textFieldDidChangeSelection(textField)
    }
}

And the view controller will be able to use the delegate as if this pass-through wasn't there.

class SomeViewController: UIViewController {
    let someTextField = CustomTextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        someTextField.customDelegate = self
    }
}

extension SomeViewController: CustomTextFieldDelegate {
    func textFieldDidChangeSelection(_ textField: UITextField) {
        // Do work
    }
}
trndjc
  • 11,654
  • 3
  • 38
  • 51
-1

You can set your viewController to be the delegate. In viewDidLoad you can add this line of code.

myTextField.delegate = self

You also need the UITextFieldDelegate protocol for the viewController.

extension MyViewController: UITextFieldDelegate {
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        //User tapped the return button
        return true
    }
}

I think there is nothing wrong with setting the delegate to the subclass. If you need to know the tap outside of your class then you will need another delegate so you might as well use my first solution. You should also be aware that if you change the delegate your code in the subclass will not be called anymore and it could lead to unexpected behavior.

Yannick
  • 3,210
  • 1
  • 21
  • 30
  • What you wrote is prefectly fine, he was asking what he can do inside of his `UITextField` subclass, and there its not recommended to use the delegate, since user of the subclass like one you mentioned above `MyViewController` would like to be the delegate :) – Ladislav Oct 17 '17 at 08:20
  • I was asking about make the textField it self the delegate something like: `textField.delegate = self` but I am aware that the ViewController can be the delegate – iOSGeek Oct 17 '17 at 08:21
  • I answered both of his questions. The first one does not ask for anything inside his subclass. It asks for a clean solution and I think setting the ViewController as a delegate is a clean solution. – Yannick Oct 17 '17 at 08:55