Detect backspace in empty UITextField

78,662

Solution 1

This may be a long shot but it could work. Try setting the text field's text to a zero width space character \u200B. When backspace is pressed on a text field that appears empty, it will actually delete your space. Then you can just reinsert the space.

May not work if the user manages to move the caret to the left of the space.

Solution 2

Swift 4:


Subclass UITextField:

// MyTextField.swift
import UIKit

protocol MyTextFieldDelegate: AnyObject {
    func textFieldDidDelete()
}

class MyTextField: UITextField {

    weak var myDelegate: MyTextFieldDelegate?

    override func deleteBackward() {
        super.deleteBackward()
        myDelegate?.textFieldDidDelete()
    }

}

Implementation:

// ViewController.swift

import UIKit

class ViewController: UIViewController, MyTextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // initialize textField
        let input = MyTextField(frame: CGRect(x: 50, y: 50, width: 150, height: 40))

        // set viewController as "myDelegate"
        input.myDelegate = self

        // add textField to view
        view.addSubview(input)

        // focus the text field
        input.becomeFirstResponder()
    }

    func textFieldDidDelete() {
        print("delete")
    }

}

Objective-C:


Subclass UITextField:

//Header
//MyTextField.h

//create delegate protocol
@protocol MyTextFieldDelegate <NSObject>
@optional
- (void)textFieldDidDelete;
@end

@interface MyTextField : UITextField<UIKeyInput>

//create "myDelegate"
@property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate;
@end

//Implementation
#import "MyTextField.h"

@implementation MyTextField

- (void)deleteBackward {
    [super deleteBackward];

    if ([_myDelegate respondsToSelector:@selector(textFieldDidDelete)]){
        [_myDelegate textFieldDidDelete];
    }
}

@end

Now simply add MyTextFieldDelegate to your UIViewController and set your UITextFields myDelegate to self:

//View Controller Header
#import "MyTextField.h"

//add "MyTextFieldDelegate" to you view controller
@interface ViewController : UIViewController <MyTextFieldDelegate>
@end

//View Controller Implementation
- (void)viewDidLoad {
    //initialize your text field
    MyTextField *input = 
     [[MyTextField alloc] initWithFrame:CGRectMake(0, 0, 70, 30)];

    //set your view controller as "myDelegate"
    input.myDelegate = self;

    //add your text field to the view
    [self.view addSubview:input];
}

//MyTextField Delegate
- (void)textFieldDidDelete {
    NSLog(@"delete");
}

Solution 3

Update: See JacobCaraballo's answer for an example that overrides -[UITextField deleteBackward].

Check out UITextInput, specifically UIKeyInput has a deleteBackward delegate method that always gets called when the delete key is pressed. If you're doing something simple, then you might consider just subclassing UILabel and making it conform to the UIKeyInput protocol, as done by SimpleTextInput and this iPhone UIKeyInput Example. Note: UITextInput and its relatives (including UIKeyInput) are only available in iOS 3.2 and later.

Solution 4

Code like following:

@interface MyTextField : UITextField
@end

@implementation MyTextField

- (void)deleteBackward
{
    [super deleteBackward];

    //At here, you can handle backspace key pressed event even the text field is empty
}

@end

At last, do forget to change the Custom Class property of the Text Field to "MyTextField"

Solution 5

Swift implementation:

import UIKit

// Extend from PinTextFieldDelegate instead of UITextFieldDelegate in your class
protocol PinTextFieldDelegate : UITextFieldDelegate {
    func didPressBackspace(_ textField: PinTextField)
}

class PinTextField: UITextField {

    override func deleteBackward() {
        super.deleteBackward()

        // If conforming to our extension protocol
        if let pinDelegate = self.delegate as? PinTextFieldDelegate {
            pinDelegate.didPressBackspace(self)
        }
    }
}
Share:
78,662
marcc
Author by

marcc

I'm a software developer in Santa Monica, CA

Updated on June 22, 2021

Comments

  • marcc
    marcc almost 3 years

    Is there any way to detect when the Backspace/Delete key is pressed in the iPhone keyboard on a UITextField that is empty? I want to know when Backspace is pressed only if the UITextField is empty.


    Based on the suggestion from @Alex Reynolds in a comment, I've added the following code while creating my text field:

    [[NSNotificationCenter defaultCenter] addObserver:self
              selector:@selector(handleTextFieldChanged:)
                  name:UITextFieldTextDidChangeNotification
                object:searchTextField];
    

    This notification is received (handleTextFieldChanged function is called), but still not when I press the Backspace key in an empty field. Any ideas?


    There seems to be some confusion around this question. I want to receive a notification when the Backspace key is pressed. That's it. But the solution must also work when the UITextField is already empty.

  • marcc
    marcc over 14 years
    Nice. I agree that it's pretty hacky, but I was considering something like this as a last resort. Thanks for the suggestion.
  • marcc
    marcc over 14 years
    @Andrew, this is the approach I decided to take. It took a bit of code, but it's certainly effective. Thanks for the help instead of trying to tell me that I'm doing something wrong.
  • ma11hew28
    ma11hew28 almost 13 years
    This technique may work on iPhone > 3.1.3, but it's hacky and may break on future versions, etc. I think I found a cleaner, more stable solution for how to detect a delete keyboard key press on the iPhone/iOS.
  • Sulthan
    Sulthan over 12 years
    Note that you should also remove the space character when the text field is not being edited. Otherwise your placeholder text won't be visible.
  • ma11hew28
    ma11hew28 over 12 years
    I can confirm that delete isn't detected if the user manages to move the cursor to the left of the space. If you can figure out how to fix that, then you should also subclass UITextField and implement canPerformAction:withSender: to return NO for select: and selectAll: actions when the text is equal to the string @"\u200B".
  • Eric G
    Eric G almost 12 years
    Only called when field is non-empty, though. Note the original question. :)
  • Pascalius
    Pascalius almost 12 years
    The method expects a boolean and not a string as return value
  • Albert Renshaw
    Albert Renshaw over 11 years
    ^I recall code for being able to detect the user's cursor location... you could search for that and then recall the becomeFirstResponder method if they move the cursor (so it moves back)
  • Yoon Lee
    Yoon Lee over 11 years
    Backstroke isn't '\b' set. But if you carefully debugging then you will see '\0'. So I get the result 0 that is two values are equal in strcmp method. const char *stoke = [text cStringUsingEncoding:NSASCIIStringEncoding]; const char *backstroke = "\0";// this is equal to \b->"\x08"; strcmp(backstroke, stoke);
  • Yoon Lee
    Yoon Lee over 11 years
    Also, by the definition of strcmp(s1, s2), returns 0 if s1 == s2, > 0 s1 is has lexicographically greater than s2 vice versa.
  • Ryan Romanchuk
    Ryan Romanchuk about 11 years
    This should be the accepted answer. Clean, and actually answers the question.
  • T.J.
    T.J. about 11 years
    This is the best solution. The answer accepted is a hack. Objective C is based on sub classing and this solution uses it properly to solve the problem.
  • BJ Homer
    BJ Homer almost 11 years
    It does answer the question... So long as you're targeting iOS 6.0+. On iOS 5, deleteBackward was simply never called on your subclass, unfortunately.
  • Jonathan.
    Jonathan. almost 11 years
    BJ Homer, 93% of devices are on iOS 6, so not targeting iOS 5 is generally not such a big deal.
  • Sam
    Sam almost 11 years
    This is the right answer. It's non-hacky and very simple with a quick subclass of UITextField.
  • Sam
    Sam almost 11 years
    Just spotted Jacob's answer below. It gives a detailed example of this.
  • Kyle Clegg
    Kyle Clegg almost 11 years
    Problem is that this doesn't work for secure test fields. Any ideas how to handle that?
  • jfeldman
    jfeldman over 10 years
    It's worth noting that this answer does not work in iOS 5. If the text field is empty pressing backspace does not invoke this method.
  • MusiGenesis
    MusiGenesis about 10 years
    I'm glad I kept scrolling down enough to find this. 100% the right way to do this today in IOS 7.
  • Alex Cio
    Alex Cio about 10 years
    Maybe a little explanation where to put this?
  • ma11hew28
    ma11hew28 almost 10 years
    It's the same with any keyboard type.
  • ma11hew28
    ma11hew28 almost 10 years
    This question is about UITextField, not UITextView.
  • rohan-patel
    rohan-patel almost 10 years
    What will happen to my existing delegate methods in ViewController class if I set my textfield's delegate to subclass of UITextField instead of UIViewController
  • chug2k
    chug2k over 9 years
    This apparently doesn't work in ios8 right now, due to what seems like an Apple Bug: devforums.apple.com/message/1045312#1045312
  • chug2k
    chug2k over 9 years
    I don't understand how this could possibly work? @YoonLee: aren't you saying strcmp returns either -1, 0, or 1? That was my understanding.
  • pIkEL
    pIkEL over 9 years
    In order for this to work in iOS8 (where there's a bug causing this delegate method never to be called), please see this answer: stackoverflow.com/a/25862878/893101 . More details on the ios8 bug: devforums.apple.com/message/1009150#1009150
  • furkan3ayraktar
    furkan3ayraktar over 9 years
    I used a workaround solution for ios8 bug as in my answer and it worked. It might be useful for the ones who are searching for a solution.
  • LolaRun
    LolaRun over 9 years
    in textview you always detect the backspace even if the there's no text, the UITextField is different
  • Brian Sachetta
    Brian Sachetta almost 9 years
    Sorry, but this idea is bad. It's incredible hacky and shouldn't be the accepted answer with 30 or so upvotes. I would subclass UITextField instead, like some of the other commenters have mentioned.
  • OxenBoxen
    OxenBoxen over 8 years
    Thanks for the great answer!
  • Friedrich 'Fred' Clausen
    Friedrich 'Fred' Clausen over 8 years
    This answer also provides a simple, non-hacky way to handle the backspace key. It's written in Swift but could be applied to Objective-C also.
  • Raj Aggrawal
    Raj Aggrawal almost 8 years
    can you write the code for swift. I got some error "redundant confirmance to protoco uikeyinput"
  • pkamb
    pkamb over 7 years
    This is a UITextViewDelegate method, not UITextFieldDelegate.
  • user230910
    user230910 about 7 years
    how do i hook this method up to my text field?
  • kalpesh jetani
    kalpesh jetani about 7 years
    Thanks, may i know this method is recommended by apple or it's hack. it seems undocumented for textfield.
  • Edouard Barbier
    Edouard Barbier almost 7 years
    Worked for me with a textView. thanks for sharing ;)
  • Christopher Hannah
    Christopher Hannah over 6 years
    I've seen so many other answers for this question that are just workarounds, and hardly any of them deal with the situation where the backspace key is pressed in an empty field. This however is perfect, and a really clean way to do it.
  • Ramakrishna
    Ramakrishna over 6 years
    Worked for me when the textfield is empty and back space is clicked.
  • Kishor Pahalwani
    Kishor Pahalwani over 6 years
    Can you please write it for swift also? Thanks
  • Faruk
    Faruk about 6 years
    it works really fine for iOS 11. really appreaciated.
  • Hemang
    Hemang almost 6 years
    This doesn't even call for me. All other delegate methods are getting called as and when for an event occurs.
  • igrrik
    igrrik over 5 years
    deleteBackward() won't be called if you return false in textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
  • Manann Sseth
    Manann Sseth about 5 years
    Thank you mate.. You nailed it.:)
  • Ian Kohlert
    Ian Kohlert over 4 years
    For the called method (textFieldDidDelete) is there a non-hacky way to do something only when the text view (in my case) was already empty? I am using it to delete a row in a table but only when tapping backspace in an empty text view. My hacky solution is adding a bool to check. So the first time the text view is empty it changes the bool. The next time it deletes. (without the bool it deletes any time the text view is empty)
  • Andy Weinstein
    Andy Weinstein about 4 years
    Tx - just what I needed. But where is it documented??
  • Himanshu padia
    Himanshu padia almost 4 years
    @McDonal_11 I think you forgot to set textfield.delegate = self of textfield.
  • McDonal_11
    McDonal_11 almost 4 years
    I have set. other UITextField's delegate methods are working fine. This one alone not working. What I miss ??
  • Michael Rogers
    Michael Rogers over 3 years
    What's your favorite charity (and it could be you 😀)? This just saved me a whole lot of work
  • jacob
    jacob over 3 years
    @MichaelRogers Haha I'm glad I was able to help. My fave charity is gktw.org (Give Kids The World) 🙂
  • Michael Rogers
    Michael Rogers over 3 years
    I made a donation in your name. Thanks again!