I have quite a few controls scattered throughout many table cells in my table, and I was wondering if there's an easier way to dismiss the keyboard without having to loop through all my controls and resigning them all as the first responder. I guess the question is.. How would I get the current first responder to the keyboard?
Here's one idea:
@interface ... {
UITextField *editingField;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField;
{
editingField = textField;
}
- (IBAction)dismissKeyboard:(id)sender;
{
[editingField resignFirstResponder];
}
Then make that class the delegate of all your UITextFields
. You could also subclass UITextField
(or whatever other control you're using) and override -becomeFirstResponder
.
Edit: The other suggested method is better. Do something like this:
@interface ... {
UITextField *someField;
}
- (IBAction)dismissKeyboard:(id)sender;
{
[someField becomeFirstResponder];
[someField resignFirstResponder];
}
and bind someField
to any UITextField
in IB. (Note that this doesn't work on desktop Cocoa, where becomeFirstResponder
is only a notification method; you need to use NSWindow
methods. Then again, desktop Cocoa actually has a method to ask for the first responder.)
A better approach is to have something "steal" first responder status.
Since UIApplication is a subclass of UIResponder, you could try:
[[UIApplication sharedApplication] becomeFirstResponder]
[[UIApplication sharedApplication] resignFirstResponder]
Failing that, create a new UITextField with a zero sized frame, add it to a view somewhere and do something similar (become followed by resign).
i am not really sure why one would need to go through all this.
consider this scenario:
i have a viewcontroller
with two textfields (username and password).
and the viewcontroller
implements UITextFieldDelegate
protocol
i do this in viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
username.delegate = self;
password.delegate = self;
}
and the viewcontroller implements the optional method as
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
and irrespective of the textfield you are in, as soon as i hit return
in the keyboard, it gets dismissed!
In your case, the same would work as long as you set all the textfield's delegate to self and implement textFieldShouldReturn
Please correct me if i am missing the obvious!!
Cheers - Prakash
I hate that there's no "global" way to programmatically dismiss the keyboard without using private API calls. Frequently, I have the need to dismiss the keyboard programmatically without knowing what object is the first responder. I've resorted to inspecting the self
using the Objective-C runtime API, enumerating through all of its properties, pulling out those which are of type UITextField
, and sending them the resignFirstResponder
message.
It shouldn't be this hard to do this...
It's not pretty, but the way I resign the firstResponder when I don't know what that the responder is:
Create an UITextField, either in IB or programmatically. Make it Hidden. Link it up to your code if you made it in IB. Then, when you want to dismiss the keyboard, you switch the responder to the invisible text field, and immediately resign it:
[self.invisibleField becomeFirstResponder];
[self.invisibleField resignFirstResponder];
You can recursively iterate through subviews, store an array of all UITextFields, and then loop through them and resign them all.
Not really a great solution, especially if you have a lot of subviews, but for simple apps it should do the trick.
I solved this in a much more complicated, but much more performant way, but using a singleton/manager for the animation engine of my app, and any time a text field became the responder, I would assign assign it to a static which would get swept up (resigned) based on certain other events... its almost impossible for me to explain in a paragraph.
Be creative, it only took me 10 minutes to think through this for my app after I found this question.
@Nicholas Riley & @Kendall Helmstetter Geln & @cannyboy:
Absolutely brilliant!
Thank you.
Considering your advice and the advice of others in this thread, this is what I've done:
What it looks like when used:
[[self appDelegate] dismissKeyboard];
(note: I added appDelegate as an addition to NSObject so I can use anywhere on anything)
What it looks like under the hood:
- (void)dismissKeyboard {
UITextField *tempTextField = [[UITextField alloc] initWithFrame:CGRectZero];
[_myRootViewController.view addSubView:tempTextField];
[tempTextField becomeFirstResponder];
[tempTextField resignFirstResponder];
[tempTextField removeFromSuperview];
[tempTextField release];
}