I have created a "utility class" whose sole purpose is to be a UITextFieldDelegate
.
Basically, it is supposed to enable a UIAlertAction
only when there is text in a textfield, otherwise the action is disabled.
class ActionDisabler: NSObject, UITextFieldDelegate {
let action: UIAlertAction
init(action: UIAlertAction, textField: UITextField) {
self.action = action
super.init()
textField.delegate = self
// Initialize it as enabled or disabled
if let text = textField.text {
action.isEnabled = !text.isEmpty
} else {
action.isEnabled = false
}
}
deinit {
print("Too early?")
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text {
action.isEnabled = text.utf8.count - string.utf8.count > 0
} else {
action.isEnabled = false
}
return true
}
}
As you can see, it takes an alert action and a textfield in its constructor and makes itself the delegate of the text field. Simple, right?
Well, this is how delegate
of UITextField
is defined:
weak open var delegate: UITextFieldDelegate?
Due to this, ActionDisabler
is de-initialized after the closure (a configuration handler for a textfield being added to a UIAlertController
it is defined in is no longer in scope.
alert.addTextField(configurationHandler: { textField in
_ = ActionDisabler(action: join, textField: textField)
})
Subclassing UIAlertController
and having each alert controller be the delegate of its own textfield is not an option, as explained by this answer.
Is there any way to make ActionDisabler
not be de-initialized until the textfield that it is a delegate of is no longer alive?