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.