Did anyone notice that UITextField calls textFieldDidEndEditing after clear button is pressed but text property still has old data ?
I'm not sure what code-sample I can provide here. I'm using storyboard if that matters.
For now I have to rely on taking data from all edit controls on main form's "Submit" button. But ideally I'd prefer to collect data in textFieldDidEndEditing handler.
Are there any better workarounds ?
I'm on iOS 6.
Update: Basically here is what I have on the form
UITextField and UiButton are on the form.
Keyboard dimissed by calling resignFirstResponder in handler of UITapGestureRecognizer
Steps to reproduce the issue:
Click on edit control. Enter some text.
Tap outside of text control.
textFieldDidEndEditing is called. Property .text has value I entered. All good.
Click on edit control again.
Click on clear button.
textFieldDidEndEditing is called again. But property .text still has value I just deleted !
Now as you see cursor blinking inside UITextField tap on Button on the form.
Keyboard is dismissed by textFieldDidEndEditing was never called.
I'll upload sample project on GitHub tomorrow.
I ran into the exact same problem. In my case, at least, it was due to having added a UITapGestureRecognizer to self.view (to allow for dismissing the keyboard if tapping outside of a UITextField) and setting cancelsTouchesInView=NO on the gesture recognizer. I had set that property in order to get hyperlinking working on a TTTAttributesLabel I have elsewhere in the View.
My workaround was to watch for keyboard show and hide notifications, and toggle that property accordingly:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShowNotification:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHideNotification:) name:UIKeyboardDidHideNotification object:nil];
(sign up for notifications)
- (void)keyboardDidShowNotification:(NSNotification*)notification
{
tapGestureRecognizer.cancelsTouchesInView = YES;
}
- (void)keyboardDidHideNotification:(NSNotification *)notification
{
tapGestureRecognizer.cancelsTouchesInView = NO;
}
(handle notifications)
The only problem, behavior-wise, is that the hyperlink still doesn't work when the keyboard is displayed: touching it will simply dismiss the keyboard, not forward the touch to the link handler. But I can live with that. After the keyboard is dismissed, the link works fine.
First check UITextFieldDelegate is assigned or not, then
implement the textFieldShouldClear delegate and write the code here clear your textField
To do this you have to set the clearButtonMode property,
yourTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
yourTextField.delegate = self;
Then implement the textFieldShouldClear delegate
.h file
#interface myViewController: UIViewController <UITextFieldDelegate>{
}
.m file
-(BOOL)textFieldShouldClear:(UITextField *)textField
yourTextFeild.text = #"";
return YES;
}
try here:
-(BOOL) textFieldShouldReturn:(UITextField*) textField
Related
Because the keyboard hides the textfields when coming up I implemented a solution for this. Now I also have built in the possibility that the user taps on the next button of the keyboard and directly jumps to the next textfield (tabbing between fields).
The problem now is that the view doesn't scroll if I use becomeFirstResponder only. The keyboard is up but the UIKeyboardDidShowNotification is not triggered and so the view doesn't slide up.
Can I fake such a notification so that the UIKeyboardDidShowNotification is sent by the notification center?
Another option is to use two great libraries for this. BSKeyboardControls for the tabbing and TPKeyboardAvoiding for moving the view.
If you just want to send the notification my guess is that [[NSNotificationCenter defaultCenter] postNotificationName: UIKeyboardDidShowNotification object:self] should work just fine.
The solution is simple:
resignFirstResponder
becomeFirstResponder
I can only provide the solution for C# (that's why I left it out first):
private bool TextFieldShouldReturn (UITextField textfield)
{
if (textfield.Tag == 1) {
UIResponder nextResponder = this.View.ViewWithTag (2);
textfield.ResignFirstResponder ();
nextResponder.BecomeFirstResponder ();
} else if(textfield.Tag == 2){
textfield.ResignFirstResponder ();
loginButton.SendActionForControlEvents (UIControlEvent.TouchUpInside);
} else {
// Not found, so remove keyboard.
textfield.ResignFirstResponder ();
}
return false; // We do not want UITextField to insert line-breaks.
}
I set some tags on each textfield. Than I use the delegate usernameText.ShouldReturn += TextFieldShouldReturn; to call my method TextFieldShouldReturn. This method selects the next textfield. To jump to the next text field you first dismiss the keyboard with resignFirstResponder and present the keyboard with becomeFirstResponder. With this code the UIKeyboardDidShowNotification is called like the user would tap on the textfield (= simulated tap).
I'm trying to get rid of the keyboard when the user touch outside my UITextField, by using this method:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[mainTextController resignFirstResponder];
[super touchesBegan:touches withEvent:event];
}
However, this seems to call a method that is called after pressing the return button on the keyboard, but I just want the keyboard to vanish, not to press return for me.
How can I accomplish that?
Thanks!
EDIT: tGilani's answer is the most straight-forward way, works like a charm, without changing to UIControl. But I guess jonkroll's answer also works.
try
[self.view endEditing:YES];
Update:
Take a boolean value and set it to false in init method. In your textFieldShouldReturn delegate method method, execute the code if it is false, skip otherwise
- (BOOL) textFieldShouldReturn:(UITextField*)textField
{
if (!boolean)
{
// YOur code logic here
}
boolean = false;
}
in your method where you call the endEditing method, set boolean to true.
boolean = YES;
[self.view endEditing:YES];
Here's how I've handled this before. First create a method on your view controller that will dismiss the keyboard by resigning first responder status on your text field:
- (IBAction)dismissKeyboard:(id)sender
{
[mainTextController resignFirstResponder];
}
Next, in your storyboard scene for your ViewController (or nib, if you are not using storyboards) change the class of your ViewController's view property from UIView to UIControl. The view property is effectively the background behind your other UI elements. The class type needs to be changed because UIView cannot respond to touch events, but UIControl (which is a direct subclass of UIView) can respond to them.
Finally, in your ViewController's viewDidLoad: method, tell your view controller to execute your dismissKeyboard method when the view receives a UIControlEventTouchDown event.
- (void)viewDidLoad
{
[super viewDidLoad];
UIControl *viewControl = (UIControl*)self.view;
[viewControl addTarget:self action:#selector(dismissKeyboard:) forControlEvents:UIControlEventTouchDown];
}
EDIT:
Part of your concern seems to be that textFieldDidEndEditing: is called when the keyboard is dismissed. That is unavoidable, it will always be called whenever a text field loses focus (i.e. first responder status). It sounds like your problem is that you have put code to perform when the user clicks the return button in textFieldDidEndEditing:. If you do not want that code to run when the user touches outside of the text field, that is not the proper place to put it.
Instead, I would put that code in a separate method:
- (IBAction)textFieldReturn:(id)sender
{
if ([mainTextController isFirstResponder]) {
[mainTextController resignFirstResponder];
// put code to run after return key pressed here...
}
}
}
and then call that method via Target-Action when your text field sends the control event UIControlEventEditingDidEndOnExit.
[mainTextController addTarget:self action:#selector(textFieldReturn:) forControlEvents:UIControlEventEditingDidEndOnExit];
Note that UIControlEventEditingDidEndOnExit is different than UIControlEventEditingDidEnd. The former is called when editing ends by the user touching outside the control, the latter is called when editing ends by the user pressing the return key.
You need to change your ViewController's view property from UIView to UIControl using the Identity Inspector:
From there, you simply create an IBAction and tell the textfield to dismiss (which I am assuming is your mainTextController). If mainTextController is not the textfield you want the keyboard to dismiss on then change the resignFirstReaponder method to your textfield like so.
- (IBAction)backgroundTap:(id)sender {
[myTextField resignFirstResponder];
}
then from there go back into your View Contoller's .xib file and connect the action to the Control View and select "Touch Down".
I do a new post because I have a problem that I can't find the respons on the internet. I'm working with a bluetooth barcoder with a clean view without any viewable textfields. To catch the information of the barcoder I use a hidden textfield and works fine. The problem is when the Barcoder disconnects it appears the keyboard because a field is the first responder. I don't want to resign that field but I don't want the keyboard appears.
I have a function that catch when the keyboard will appear:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector (keyboardWillShow:)
name: UIKeyboardWillShowNotification object:nil];
What I want is to stop the event of the keyboard or if not's possible hide it when appears. Any ideas about it? Any help will very usefull...
Thanks guys!
Dhilip's answer may work for you. If it doesn't here are some alternatives:
1) set the textField.enabled property to NO.
2) Subclass UITextField and return nil for the inputView:
#interface MyTextField: UITextField
#end
#implementation MyTextField
- (void)inputView
{
return nil;
}
#end
If you use your custom textfield class instead of a regular UITextField, it works the same except that you've said to use nil for it's keyboard instead of UIKeyboardView (which is the default).
I cannot understand your question properly, but still i got a suggestion for you.
If you are setting the text in UITextField programmatically, you can set userInteractionEnabled property to No.
When I delete characters from a UITextField field one-by-one, the delegate method textField:shouldChangeCharactersInRange:replacementString: is called.
When I type a full line of characters into a textfield, and then hold down the delete key, however iOS at first calls the delegate for each character it deletes. But at some point (about half way through the line) it just deletes everything that remains. The strange thing is that textField:shouldChangeCharactersInRange:replacementString: is not called when this happens. Neither is textFieldShouldClear:.
How can I detect this event? I want to update UI when the textfield is empty. And if I empty it in this fashion, my code fails to detect.
You can register an object to observe UITextFieldDidChangeNotification on your text field.
For example:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFieldDidChange:) name:UITextFieldTextDidChangeNotification object:self.textField];
}
then
- (void)textFieldDidChange:(NSNotification *)notification
{
UITextField *aTextField = [notification object];
if ([aTextField.text length] == 0) {
aTextField.backgroundColor = [UIColor redColor];
}
}
if you set a breakpoint on
aTextField.backgroundColor = [UIColor redColor];
You will see that it is called right before the last deletion occurs that sets the text field's text property to nil.
You could also simply access your property self.textField, but I am demonstrating how to access the object the notification references. If you leave out the last parameter (object:) in -addObserver:selector:name:object: it will call the notification for all textFields in that object's instance.
I have an UITextField in a MyCustomUIView class and when the UITextField loses focus, I'd like to hide the field and show something else in place.
The delegate for the UITextField is set to MyCustomUIView via IB and I also have 'Did End On Exit' and 'Editing Did End' events pointing to an IBAction method within MyCustomUIView.
#interface MyCustomUIView : UIView {
IBOutlet UITextField *myTextField;
}
-(IBAction)textFieldLostFocus:(UITextField *)textField;
#end
However, neither of these events seem to get fired when the UITextField loses focus. How do you trap/look for this event?
The delegate for the UITextField is set as MyCustomUIView so I am receiving textFieldShouldReturn message to dismiss the keyboard when done.
But what I'm also interested in is figuring when the user presses some other area on the screen (say another control or just blank area) and the text field has lost focus.
Try using delegate for the following method:
- (BOOL) textFieldShouldEndEditing:(UITextField *)textField {
NSLog(#"Lost Focus for content: %#", textField.text);
return YES;
}
That worked for me.
I believe you need to designate your view as a UITextField delegate like so:
#interface MyCustomUIView : UIView <UITextFieldDelegate> {
As an added bonus, this is how you get the keyboard to go away when they press the "done" or return buttons, depending on how you have set that property:
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
//This line dismisses the keyboard.
[theTextField resignFirstResponder];
//Your view manipulation here if you moved the view up due to the keyboard etc.
return YES;
}
The problem with the resignFirstResponder solution solely is, that it can only be triggered by an explicit keyboard or UITextField event.
I was also looking for a "lost focus event" to hide the keyboard, if somewhere outside the textfield was tapped on.
The only close and practical "solution" I came across is, to disable interactions for other views until the user is finished with the editing (hitting done/return on the keyboard) but still to be able to jump between the textfields to make corrections without the need of sliding out and in the keyboard everytime.
The following snippet maybe useful to someone, who wants to do the same thing:
// disable all views but textfields
// assign this action to all textfields in IB for the event "Editing Did Begin"
-(IBAction) lockKeyboard : (id) sender {
for(UIView *v in [(UIView*)sender superview].subviews)
if (![v isKindOfClass:[UITextField class]]) v.userInteractionEnabled = NO;
}
// reenable interactions
// assign this action to all textfields in IB for the event "Did End On Exit"
-(IBAction) disMissKeyboard : (id) sender {
[(UIResponder*)sender resignFirstResponder]; // hide keyboard
for(UIView *v in [(UIView*)sender superview].subviews)
v.userInteractionEnabled = YES;
}
You might have to subclass the UITextField and override resignFirstResponder. resignFirstResponder will be called just as the text field is losing focus.
i think you have implemented UIKeyboardDidHideNotification and in this event you
use code like
[theTextField resignFirstResponder];
remove this code.
also same code write in textFieldShouldReturn method. this also lost focus.
In Swift, you need to implement the UITextFieldDelegate to your ViewController and implement the method textFieldDidEndEditing from the delegate:
class ViewController: UIViewController, UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
// will be called when the text field loses their focus
}
}
Then you need to asign the delegate of your textField:
textField.delegate = self
For those struggling with this in Swift. We add a gesture recognizer to the ViewController's view so that when the view is tapped we dismiss the textfield. It is important to not cancel the subsequent clicks on the view.
Swift 2.3
override func viewDidLoad() {
//.....
let viewTapGestureRec = UITapGestureRecognizer(target: self, action: #selector(handleViewTap(_:)))
//this line is important
viewTapGestureRec.cancelsTouchesInView = false
self.view.addGestureRecognizer(viewTapGestureRec)
//.....
}
func handleViewTap(recognizer: UIGestureRecognizer) {
myTextField.resignFirstResponder()
}