Reputation: 251
I have a subclass of UITextField used to call two methods after specific textField events. The textField calls the methods in the textField's superclass with a delegate/protocol setup.
class SearchTermCellTextField: UITextField {
var searchTermCellTextFieldDelegate: SearchTermCellTextFieldDelegate?
override var text: String? {
didSet {
searchTermCellTextFieldDelegate?.textFieldDidChange(self)
}
}
override func deleteBackward() {
super.deleteBackward()
searchTermCellTextFieldDelegate?.textFieldReceivedDelete(self)
}
}
protocol SearchTermCellTextFieldDelegate {
func textFieldReceivedDelete(_ textField: UITextField)
func textFieldDidChange(_ textField: UITextField)
}
The delegate is initialized correctly and textFieldReceivedDelete()
is called without problem. However, each time textFieldDidChange()
is called (in var text { didSet }
), searchTermCellTextFieldDelegate
has a nil value.
I tried placing searchTermCellTextFieldDelegate?.textFieldDidChange()
into a secondary method called by the didSet to see if it would have any effect, but still the same. I tested it from within deleteBackward()
— where I don't want it — and searchTermCellTextFieldDelegate?
has its non-nil value as expected and it fires fine.
My only guess is that there's something more complex happening within the text variable's { get set }
that causes the issue, but beyond that I don't know where to start problem solving.
Does anyone have any insight? Thanks in advance.
Upvotes: 0
Views: 482
Reputation: 4855
Reason - You did Override text of A textField but the function textFieldDidChange
that OP want to trigger is based on Editing changed Control Event , Thus Overriding text
was not required in your case as text wont be triggered when its value is changed or edited
So, To make that class delegate work you actually need to keep eye on editing change control Event of TextField
Try this
import Foundation
import UIKit
class SearchTermCellTextField: UITextField {
var TFDelegate : SearchTermCellTextFieldDelegate?
/// Initialise class
override init(frame: CGRect) {
super.init(frame: frame)
/// Need to add a target to notify class that text did changed
self.addTarget(self, action: #selector(SearchTermCellTextField.editingChanged), for: .editingChanged)
}
/// Coder
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/// You override Text Not its editing changed
override var text: String? {
didSet {
TFDelegate?.textFieldDidChange(self)
}
}
/// Handler which tells that editing has been changed
@objc func editingChanged(){
TFDelegate?.textFieldDidChange(self)
}
/// Its Working
override func deleteBackward() {
super.deleteBackward()
TFDelegate?.textFieldReceivedDelete(self)
}
}
protocol SearchTermCellTextFieldDelegate {
func textFieldReceivedDelete(_ textField: UITextField)
func textFieldDidChange(_ textField: UITextField)
}
ViewController class
import UIKit
class ViewController: UIViewController {
private var myFirstTF : SearchTermCellTextField?
}
/// View Life cycles
extension ViewController
{
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myFirstTF = SearchTermCellTextField()
myFirstTF?.TFDelegate = self
myFirstTF?.placeholder = "Enter Text"
myFirstTF?.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(myFirstTF!)
myFirstTF?.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20).isActive=true
myFirstTF?.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 20).isActive=true
myFirstTF?.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100).isActive=true
myFirstTF?.heightAnchor.constraint(equalToConstant: 50)
}
}
extension ViewController: SearchTermCellTextFieldDelegate
{
func textFieldReceivedDelete(_ textField: UITextField) {
print("delete Recieved")
}
func textFieldDidChange(_ textField: UITextField) {
print("Text:\(textField.text ?? "Empty")")
}
}
Console Output
Upvotes: 1