I am writing a custom UITextField right now in Swift, and encountered the following:
class MyField: UITextField {
open override var text: String? {
didSet {
// some logic that normalizes the text
}
}
private func setup() { //called on init
addTarget(self, action: #selector(textEditingChanged(_:)), for: .editingChanged)
}
@objc func textEditingChanged(_ sender: UITextField) {
}
}
Now, when testing this, I observed that, when the user is typing something, textEditingChanged is called, but text.didSet is not. Neither is text.willSet, for that matter. However, in textEditingChanged, the textfield's text will already be updated to the new value.
Can anyone explain what is going on here? Is Swift circumventing the setter on purpose? How am I supposed to know when/if the setter is called, is there any logic to this in UIKit?
The text property of the
UITextFieldis only for external use, when you are typingUIKithandles the update internally. Can't really tell whats going on under the hood, as we do not have access toUIKitimplementation but one possible answer to the question is thatUITextFieldis using an other internal variable for storing the text property. When you are getting the text property, you are actually getting that internal value, and when you are setting it, you are setting that internal value also. Of course under the hood it is a bit more complicated but it may look something like this(SampleUITextFieldrepresents theUITextField):And when you subclass it it looks like:
Now when you set the text property directly the
didSetis called because thetextvalue updates. You can check it:But now when you call
updateInternalTextWiththedidSetis not called:That's because you are not updating the text value directly, but just the internal text property. A similar method is called to update the internal text variable of the
UITextFieldwhen you are typing, and that's the reason thedidSetis not called in your case.For that reason, it is not enough to override the
textvariable when we want to be notified when the text properties changes, and we need to use delegate(UITextFieldDelegate) methods or notifications (textFieldDidChange) to catch the actual change.