Detect backspace in empty UITextField
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)
}
}
}
Comments
-
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 theUITextField
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 over 14 yearsNice. I agree that it's pretty hacky, but I was considering something like this as a last resort. Thanks for the suggestion.
-
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 almost 13 yearsThis 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 over 12 yearsNote 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 over 12 yearsI 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 implementcanPerformAction:withSender:
toreturn NO
forselect:
andselectAll:
actions when the text is equal to the string@"\u200B"
. -
Eric G almost 12 yearsOnly called when field is non-empty, though. Note the original question. :)
-
Pascalius almost 12 yearsThe method expects a boolean and not a string as return value
-
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 over 11 yearsBackstroke 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 over 11 yearsAlso, by the definition of strcmp(s1, s2), returns 0 if s1 == s2, > 0 s1 is has lexicographically greater than s2 vice versa.
-
Ryan Romanchuk about 11 yearsThis should be the accepted answer. Clean, and actually answers the question.
-
T.J. about 11 yearsThis 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 almost 11 yearsIt 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. almost 11 yearsBJ Homer, 93% of devices are on iOS 6, so not targeting iOS 5 is generally not such a big deal.
-
Sam almost 11 yearsThis is the right answer. It's non-hacky and very simple with a quick subclass of UITextField.
-
Sam almost 11 yearsJust spotted Jacob's answer below. It gives a detailed example of this.
-
Kyle Clegg almost 11 yearsProblem is that this doesn't work for secure test fields. Any ideas how to handle that?
-
jfeldman over 10 yearsIt'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 about 10 yearsI'm glad I kept scrolling down enough to find this. 100% the right way to do this today in IOS 7.
-
Alex Cio about 10 yearsMaybe a little explanation where to put this?
-
ma11hew28 almost 10 yearsIt's the same with any keyboard type.
-
ma11hew28 almost 10 yearsThis question is about
UITextField
, notUITextView
. -
rohan-patel almost 10 yearsWhat will happen to my existing delegate methods in
ViewController
class if I set my textfield's delegate to subclass ofUITextField
instead ofUIViewController
-
chug2k over 9 yearsThis apparently doesn't work in ios8 right now, due to what seems like an Apple Bug: devforums.apple.com/message/1045312#1045312
-
chug2k over 9 yearsI 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 over 9 yearsIn 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 over 9 yearsI 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 over 9 yearsin textview you always detect the backspace even if the there's no text, the UITextField is different
-
Brian Sachetta almost 9 yearsSorry, 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 over 8 yearsThanks for the great answer!
-
Friedrich 'Fred' Clausen over 8 yearsThis 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 almost 8 yearscan you write the code for swift. I got some error "redundant confirmance to protoco uikeyinput"
-
pkamb over 7 yearsThis is a
UITextViewDelegate
method, notUITextFieldDelegate
. -
user230910 about 7 yearshow do i hook this method up to my text field?
-
kalpesh jetani about 7 yearsThanks, may i know this method is recommended by apple or it's hack. it seems undocumented for textfield.
-
Edouard Barbier almost 7 yearsWorked for me with a textView. thanks for sharing ;)
-
Christopher Hannah over 6 yearsI'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 over 6 yearsWorked for me when the textfield is empty and back space is clicked.
-
Kishor Pahalwani over 6 yearsCan you please write it for swift also? Thanks
-
Faruk about 6 yearsit works really fine for iOS 11. really appreaciated.
-
Hemang almost 6 yearsThis doesn't even call for me. All other delegate methods are getting called as and when for an event occurs.
-
igrrik over 5 years
deleteBackward()
won't be called if youreturn false
intextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
-
Manann Sseth about 5 yearsThank you mate.. You nailed it.:)
-
Ian Kohlert over 4 yearsFor 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 about 4 yearsTx - just what I needed. But where is it documented??
-
Himanshu padia almost 4 years@McDonal_11 I think you forgot to set textfield.delegate = self of textfield.
-
McDonal_11 almost 4 yearsI have set. other UITextField's delegate methods are working fine. This one alone not working. What I miss ??
-
Michael Rogers over 3 yearsWhat's your favorite charity (and it could be you 😀)? This just saved me a whole lot of work
-
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 over 3 yearsI made a donation in your name. Thanks again!