Joe.b
Joe.b

Reputation: 542

Swift UITextField subclass handle text change programmatically

I have a subclass of UITextField that is specific to handle Date text. I have a tableviewcell that uses this text field:

let dateInput: DateTextField

Now the controller needs to initialize the text of the dateInput prior to display as follows:

cell.dateInput.text = "01/29/2016"

Now, I want to be able to detect that the text changed from the subclass so that I can update the internal date variable so that is it in-sync with the text.

I implemented the textfield delegate methods but that just catches changes made by the user and not programmatically.

Upvotes: 11

Views: 7719

Answers (4)

Fattie
Fattie

Reputation: 12621

It's now incredibly easy to do this:

addTarget(self, action: #selector(userTyping), for: .editingChanged)

That's it.

@objc func userTyping() {
    print("user is typing, text is now", text)
}

Upvotes: 0

James Webster
James Webster

Reputation: 32066

My solution for this is to have each instance of the subclass maintain its own notification for UITextFieldDidChange and use a custom protocol to relay that information to the listener.

protocol MutableTextFieldDelegate {
    func textChanged(_ sender:MutableTextField)
}

class MutableTextField : UITextField {

    var textChangedDelegate : MutableTextFieldDelegate?

    var previousValue : String?

    override func awakeFromNib() {
        super.awakeFromNib()
        NotificationCenter.default.addObserver(forName: .UITextFieldTextDidChange, object: self, queue: nil) { [weak self] notification in
            guard let strongSelf = self else { return }
            guard let object = notification.object as? MutableTextField, object == strongSelf else { return }

            if strongSelf.previousValue != strongSelf.text {
                strongSelf.textChangedDelegate?.textChanged(strongSelf)
            }
            strongSelf.previousValue = strongSelf.text
        }
    }
}

swift5: NotificationCenter.default.addObserver(forName: UITextField.textDidChangeNotification ...

Upvotes: 4

Konstantine Kalbazov
Konstantine Kalbazov

Reputation: 2673

You can override property and add didSet observer in your custom class:

class DateTextField: UITextField {

    override var text: String? {
        didSet {
           // Do your stuff here    
        }
    }   
}

Upvotes: 10

ksa_coder
ksa_coder

Reputation: 1413

Check the UIControlEventEditingChanged event...within it, you can set following logic.

Example from this post:

// Add a "textFieldDidChange" notification method to the text field control.
[textField addTarget:self 
              action:@selector(textFieldDidChange:) 
    forControlEvents:UIControlEventEditingChanged];

Upvotes: 2

Related Questions