When UITextField contains nothing, pressing the delete key of keyboard won't call any of UITextFieldDelegate's methods.
How can I detect it?
EDIT: There seems no trivial way to do it. The most useful links I can find are:
UITextField : Any way to detect the Delete key event when the field is empty ?
How to get the actual key pressed in a UITextField
In short, my solution is to put a permanent SPACE at the start of the text field. And make other nesessary changes(textFieldShouldReturn:, textField:shouldChangeCharactersInRange:replacementString:, etc.).
I'm adding this answer for a more complete example in swift 3. Basically, I needed a pincode type view where I have multiple text fields that allow one character in each cell.
like this I started by creating a subclass of UITextField and a protocol that defines a new func.
protocol MYDeleteActionTextFieldDelegate {
func textFieldDidSelectDeleteButton(_ textField: UITextField) -> Void
}
class MYDeleteActionTextField: UITextField {
var deleteDelegate: MYDeleteActionTextFieldDelegate?
override func deleteBackward() {
// Need to call this before super or the textfield edit may already be in place
self.deleteDelegate?.textFieldDidSelectDeleteButton(self)
super.deleteBackward()
}
}
Then you create the text fields with the new subclass and implement the delegate in your view controller. In my case, I manage the textfields in an array for ease of use and layout the cells with PureLayout. I store them like this
var pinFields = UITextField
Then in viewDidLoad()
, I add all the pin fields into the array like so:
for _ in 1...6 {
let field = EDFDeleteActionTextField.init(forAutoLayout: ())
field.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
field.delegate = self
field.deleteDelegate = self
field.textAlignment = .center
field.font = UIFont.newBigTitle()
field.textColor = UIColor.edfBlue()
field.backgroundColor = UIColor.edfWhite()
self.pinFields.append(field)
self.pinView.addSubview(field)
}
Now you just need to respond to all the appropriate delegate methods and the textFieldDidChange
target that was added above.
// MARK: UITextFieldDelegate
func textFieldDidChange(textField: UITextField) {
// If the user typed one character, move to the next cell.
if (textField.text?.characters.count == 1) {
let index = pinFields.index(of: textField)
textField.resignFirstResponder()
if (pinFields.count > index! + 1) {
pinFields[index! + 1].becomeFirstResponder()
}
} // If they deleted the character move to previous cell
else if (textField.text?.characters.count == 0) {
let index = pinFields.index(of: textField)
if (index! - 1 >= 0) {
pinFields[index! - 1].becomeFirstResponder()
}
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if range.location > 0 {
let index = pinFields.index(of: textField)
// If there is already text in the text field and the next cell is empty - move the newly typed character to that cell.
if (pinFields.count > index! + 1) {
let nextField = pinFields[index! + 1]
if (nextField.text?.characters.count == 0) {
textField.resignFirstResponder()
nextField.becomeFirstResponder()
nextField.text = string
}
}
return false
}
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
// MARK: EDFDeleteActionTextFieldDelegate
func textFieldDidSelectDeleteButton(_ textField: UITextField) {
// If user clicked delete, and there are no characters, move to previous cell if available.
// If there are characters, it is handled in UITextFieldDelegate
if (textField.text?.characters.count == 0) {
let index = pinFields.index(of: textField)
if (index! - 1 >= 0) {
pinFields[index! - 1].becomeFirstResponder()
}
else {
textField.resignFirstResponder()
}
}
}
I'll leave out the boring parts (like laying out text fields etc), since this general functionality is useful in more cases than this pincode view, but implementing this child class and protocol should give all the functionality that you would need for similar type views and solve for the question at hand (which is probably needing something similar).
Happy coding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With