Detect backspace Event in UITextField
Swift 4.2
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if let char = string.cString(using: String.Encoding.utf8) {
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
print("Backspace was pressed")
}
}
return true
}
Older Swift version
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
println("Backspace was pressed")
}
return true
}
I prefer subclassing UITextField
and overriding deleteBackward()
because that is much more reliable than the hack of using shouldChangeCharactersInRange
:
class MyTextField: UITextField {
override public func deleteBackward() {
if text == "" {
// do something when backspace is tapped/entered in an empty text field
}
// do something for every backspace
super.deleteBackward()
}
}
The shouldChangeCharactersInRange
hack combined with an invisible character that is placed in the text field has several disadvantages:
- with a keyboard attached, one can place the cursor before the invisible character and the backspace isn't detected anymore,
- the user can even select that invisible character (using
Shift Arrow
on a keyboard or even by tapping on the caret) and will be confused about that weird character, - the autocomplete bar offers weird choices as long as there's only this invisible character,
- Asian language keyboards that have candidate options based on the text field's text will be confused,
- the
placeholder
isn't shown anymore, - the clear button is displayed even when it shouldn't for
clearButtonMode = .whileEditing
.
Of course, overriding deleteBackward()
is a bit inconvenient due to the need of subclassing. But the better UX makes it worth the effort!
And if subclassing is a no-go, e.g. when using UISearchBar
with its embedded UITextField
, method swizzling should be fine, too.