short version: How can I make a UITextField box remove all content on the users first keypress? I don't want the info removed until the user starts typing something. ie, clearing it on begin edit is not good enough.
long version: I have three UITextField that loop around (using the return key and catching the press in the "shouldReturn" method. There is text already in the UITextField, and if the user doesn't type anything and just goes to the next UITextField, the value should stay (default behaviour).
But I want it that if the user starts typing, it automatically clears the text first. Something like having the whole field highlighted, and then typing anything deletes the fiels and then adds the user keypress.
"Clear when editing begins" is no good, because the text is immediately cleared on the cursor appearing in the field. That's not desired. I thought I could use the placeholder here, but that doesn't work as a default, and I can't find a default value property. The Highlighted and Selected properties don't do anything in this regard either.
There is a delegate method called
textFieldDidBeginEditing:(UITextField*) tf{
tf.startedEdinting = YES;
}
textFeildDidEndEditing: (UITextField*) tf {
tf.startedEditing = NO;
}
Add startEditing in a category to UITextField.
Then if value changes clear the field:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.startEditing){
textField.text = string;
} else {
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
}
}
You can add the property to the UITextField category in the following way:
.h
#property (nonatomic, assign) BOOL startEditing;
.m
#dynamic startEditing;
- (void) setStartEditing:(BOOL)startEditing_in{
NSNumber* num = [NSNumber numberWithBool:startEditing_in];
objc_setAssociatedObject(self, myConstant, num, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL) startEditing{
NSNumber* num = objc_getAssociatedObject(self, myConstant);
return [num boolValue];
}
Declare a BOOL variable in your .h file like.
BOOL clearField;
And implement the delegate methods like:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
clearField = YES;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
clearField = NO;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
clearField = NO;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(clearField)
{
textField.text = #""
clearField = NO;
}
}
I want to thank people for their answers, I implemented both of the main methods described here and both worked flawlessly. But I have since come across a much simpler, nicer answer and involves only one line of code :)
In the textField's didBeginEditing method, place [self.textField selectAll:self]; or [self.textField selectAll:nil];
The original answer I found had selectAll:self but this shows the cut/copy/paste menu. If you send nil instead of self the menu doesn't appear.
Adding this one line of code highlights the text on entering the textField (so gives the user a visual cue), and only removes everything once a key is pressed.
Another solution that fulfils the same purpose is by simply using a text field placeholder which is defined as:
The string that is displayed when there is no other text in the text field.
So as soon as the user starts typing, the placeholder text disappears.
That's something you can set from the storyboard, or programmatically. (Yes it took me two hours trying to figure it the harder way.. when the solution was literally one line change of code).
If you want to clear the text one the user interacts with it, there is an option in interface builder to where you can set the text field to "Clear when editing begins."
Try to use the following method.
- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {
if(isFirsttime==YES)
{
textfield.text==#"";
isFirsttime=NO;
}
return YES;
}
Declare and initialize a NSString variable for your textField's initial text
NSString *initialText=#"initial text";
Then implement methods:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
if(textField.text isEqualToString:initialText)
{
textField.text=#"";
}
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
if(textField.text isEqualToString:#"")
{
textField.text=initialText;
}
}
Related
I have a table view. In cellForRowAtIndexPath I have a cell and in that cell there is UITextField. I set textfield's delegate like this: cell.textField.delegate = self;. I need to call my API on third character. So when user types 3 character in textfield, API is called hence shouldChangeCharactersInRange.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.text.length >= 2) {
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring
stringByReplacingCharactersInRange:range withString:string];
[API CALLED WITH BLOCK WITH TEXTFIELD TEXT AS PARAMETER:substring];
}
return YES;
}
The problem is that when I type for example "abc" shouldChangeCharactersInRange is called first time and parameter is "abc". Second after, shouldChangeCharactersInRange is again called and my textfield has another added character which I did not type and it is always last character that is copied. So in this example, it sends "abcc". Do you know, what is the problem?
Setting breakpoints in that delegate method can sometimes cause the method to be fired twice. Try removing any breakpoints that are hit here or in your API method and test again.
This can be replicated easily. Create a new project, add a UITextField outlet and set the delegate to your controller. Implement textField:shouldChangeCharactersInRange: in your controller and set a breakpoint on an NSLog statement or something, and return YES. Sometimes, after telling the debugger to continue, a second keystroke will be generated and will hit your delegate method again.
I would recommend using a textFieldDidChange instead as this occurs after the text has been typed so you don't have to deal with appending strings. From there you can just check 'text.lenght >=3' to fire your API call.
You can add the event like this:
[textField addTarget:self
action:#selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];
EDIT:
This code works for me. I sent up the delegate in the cell class.
#import "AnotherTableViewCell.h"
#implementation AnotherTableViewCell
#synthesize myTextField = _myTextField;
- (void)awakeFromNib {
// Initialization code
_myTextField.delegate=self;
[_myTextField addTarget:self
action:#selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)textFieldDidChange:(UITextField*)textField{
if (textField.text.length>=3) {
NSLog(#"Text >= 3: %#",textField.text);
}
}
#end
While trying to allow multi token deletions, as user holds the backspace key in VENTokenField to act the same as the native email app, or messages app, I have come across many problems...
First, I can only detect one tap on the backspace key from the initial code the VENToken's UITextField subclass offer (which is technically touching private API) - (BOOL)keyboardInputShouldDelete:(UITextField *)textField. That is fine, but not helpful for detecting long press on backspace button, which only works while you actually have characters in a certain UITextField, and not while the UITextField is empty such as in our case.
I have also came across this blogpost which suggest another approach of accessing more of the private API, however, does not offer solution to my problem. As it's not documented, I was wondering if there is a valid way to detect this event at all?
I've resolved it by first, comment out anything that was in VENBackspaceTextField class'
keyboardInputShouldDelete:(UITextField *)textField
Then, added 2 consts in VENTokenField header:
NSString * const kTextEmpty = #"\u200B"; // Zero-Width Space
NSString * const kTextHidden = #"\u200D"; // Zero-Width Joiner
Everytime the token becomes first responder, make sure the textField has the empty text:
- (void)inputTextFieldBecomeFirstResponder {
[self.inputTextField becomeFirstResponder];
if (self.tokens.count) {
[self.inputTextField setText:kTextEmpty];
}
...
}
And set it to hidden when cursor is not visible:
- (void)setCursorVisibility {
NSArray *highlightedTokens = [self.tokens filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(VENToken *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.highlighted;
}]];
BOOL visible = [highlightedTokens count] == 0;
if (visible) {
[self inputTextFieldBecomeFirstResponder];
} else {
[self.invisibleTextField becomeFirstResponder];
[self.invisibleTextField setText:kTextHidden];
}
}
Then, modified the textField Delegate method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (self.tokens.count && [string isEqualToString:#""] && [textField.text isEqualToString:kTextEmpty]){
VENToken *lastToken = [self.tokens lastObject];
lastToken.highlighted = YES;
[_inputTextField setText:kTextHidden];
_inputTextField.alpha = 0.0;
return NO;
}
if ([textField.text isEqualToString:kTextHidden]){
[self deleteHighlighted];
[self unhighlightAllTokens];
return (![string isEqualToString:#""]);
}
//If there are any highlighted tokens, delete
[self deleteHighlighted];
return YES;
}
I have a UITextField called place, it's text property contains an NSString. I would like to clear the existing content from the text property when the user taps into the text field.
I tried the code above, but nothing happened. I also tried it with the placeholder property, but it was the same. Do you have any idea what could be the problem? I think it should work.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
self.place.text = nil;
}
2, version - in this case nothing appears in the text field from the beginning
- (void)viewDidLoad
{
[super viewDidLoad];
...
[self textFieldDidBeginEditing:place];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
textField.text = nil;
}
There is a property clearsOnBeginEditing you can set to YES programmatically or there is a checkbox in Interface Builder.
If you also want to clear your placeholder
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
textField.placeholder = nil;
}
Double check that the UITextField self.place has it's delegate set to your view controller and validate that textFieldDidBeginEditing is being called.
how to clear text field in ios,
How can I make a textfield box remove all content on the users first keypress?
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([tfieldDOB.text length] == 4)
{
tfieldDOB.text=[NSString stringWithFormat:#"%#/",tfieldDOB.text];
}
else if([tfieldDOB.text length]==7)
{
tfieldDOB.text=[NSString stringWithFormat:#"%#/",tfieldDOB.text];
}
return YES;
}
change the textfield attribute clear button mode in appears while editing
or other choice just use the single line, where you need to add
yourtextfieldname.text=#""; //it is used for clear the textfield values
Swift
yourtextfieldname.text=""
or another way
clearField =#"YES";
if([clearField isequaltostring:#"YES"]) //check this line in
{
tfieldDOB.text = #"";
clearField =#"NO";
}
Implement the text field's delegate method textFieldShouldBeginEditing: and set the text as empty string when the text field is just about to being editing.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
[textField setText:#""];
return YES;
}
Or you can set the property clearsOnBeginEditing of the textfield as
[textField setClearsOnBeginEditing:YES];
and it will clear the text when editing begins
I have a table with UITextFields, and I want to make it so that when a textfield is selected, the current info is cleared (to allow new input), but if the user decides (after selecting) that they don't want to change it, I want them to be able to click elsewhere and the data from before reappears in the textfield.
Is there an easy way to do this?
A good way to do this that's nice and user friendly is to use the placeholder property. Set up your viewController as the textfield's delegate (as described by Andeh) then add the following code:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
textField.placeholder = textField.text;
textField.text = #"";
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField.text.length == 0) {
textField.text = textField.placeholder;
}
textField.placeholder = #"";
}
And you're done. If you have multiple UITextFields on the page and you don't want this behaviour for all of them you can add a check to the methods above.
In the textFieldDidBeginEditing delegate method, save the current value to a persisting variable before clearing the UITextField. Then in the didFinishEditing delegate method, if the new length of the user input is 0 set the text back to the stored value!
UITextField Delegate docs for reference.
First I think you have two sets of behaviors here.
The text field must clear the value when you begin editing. This exists: -clearsOnBeginEditing.
The text field must restore the previous text if text is empty. Subclassing seems the better solution.
Here is a possible sample class:
// MyRestoringTextField.h
#interface MyRestoringTextField : UITextField
#end
// MyTextField.m
#interface MyRestoringTextField ()
#property (strong, nonatomic) NSString *previousText;
#end
#implementation MyRestoringTextField
- (BOOL)becomeFirstResponder
{
BOOL result = [super becomeFirstResponder];
self.previousText = self.text;
return result;
}
- (BOOL)resignFirstResponder
{
BOOL result = [super resignFirstResponder];
if (self.text.length == 0)
self.text = self.previousText;
return result;
}
#end
Hope that helps.
To clear and then restore a textField if you fail to make an entry, use the following delegates as such:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[[NSUserDefaults standardUserDefaults] setObject:textField.text forKey:kTextFieldIdentifier];
textField.text = #"";
}
-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
if ([textField.text isEqualToString:#""])
textField.text = [[NSUserDefaults standardUserDefaults]
stringForKey:kTextFieldIdentifier];
return YES;
}
As of iOS 8.1, textFieldDidBeginEditing is already receiving a cleared text. You should use
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField
to initialized the placeholder field.