How to identify which textfield is currently first responder - iphone

If you have several text fields on the screen, and the keyboard pops up for each one when they are tapped, what if you want to programmatically hide the keyboard, or resign first responder, but you don't know which textfield to send the resignFirstResponder message to? Is there a way to identify which object/textField should get this message?

check all of your textfield call
[textfield isFirstResponder]

You could keep track of which text field is the first responder by either setting your view controller to be the delegate object of all text fields and then when your subclassed text fields gets the "becomeFirstResponder" method call, tell your view controller which text field is the current one.
Or, there's a more blunt force approach which is a category extension to "UIView":
#implementation UIView (FindAndResignFirstResponder)
- (BOOL)findAndResignFirstResponder
{
if (self.isFirstResponder) {
[self resignFirstResponder];
return YES;
}
for (UIView *subView in self.subviews) {
if ([subView findAndResignFirstResponder])
return YES;
}
return NO;
}
#end
which I got from this potentially very related question.

You Can Check Your all TextField and than Identify Easily.
[textfield isFirstResponder];

There is no public method to get the current first responder, but you can do things to still get it; The first one is obviously to keep track of this yourself. You can do this in various way and if you don't want to touch any existing class but just want it to work, a category and method swizzling will do the trick. The more cleaner solution however is to iterate through the view hierarchy and ask the views wether they are the current first responder. You can start with the root UIWindow and start iterating, or you can start with your current UIViewController's view, but keep in mind that the current first responder doesn't have to be part of your roots UIWindow view hierarchy (eg. if you have a text field inside an UIAlertView).

Try this (Swift 3):
if textField.isEditing {
textField.resingFirstResponder()
}

Related

Tell any UITextField to dismiss

How can I tell the current firstResponder to resign? I have a UITableView with a bunch of TextFields and I don't know which is active at all times. I thought about storing pointers to all cells in an array and iterating through it, telling every cell to resignFirstResponder but I'm sure there is an easier way. Maybe something like [CurrentFirstResponder resignFirstResponder]?
I would appreciate some help, Fabian
EDIT: I don't want to dismiss the keyboard when the user taps done. It should be dismissed programmatically. Since I don't know which UITextField is active at any time, I am searching for something that calls resignFirstResponder on the current FirstResponder.
You could keep a reference to the UITextfeild that's actively editing using textFieldDidBeginEditing: on the UITextFieldDelegate Protocol or you could do this with your parent view:
UIView * myParentViewView;//view containing one or more editable UI controls
[myParentViewView endEditing:YES];
I hope this will solve your problem,
Assign delegate to UItextField,
textField.delegate=self;
then in following method
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
//This for to resign on begin editing
[textField resignFirstResponder];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
//This for to resign on end editing
[textField resignFirstResponder];
}
If you dont want to the textField to be editable then,
textField.editing=NO;
Set tag to distingush your textFields
Simply use the UITextFieldDelegate (reference). Whenever - (BOOL)textFieldShouldReturn:(UITextField *)textField is called, perform [textField resignFirstResponder], since this method is always invoked with the currently active textfield.
If you still need to distinguish between your textfields, try setting a tag and use it with if(textfield.tag == self.mytextfield.tag) {...}

iPhone SDK: resignFirstResponder not working

For some reason, resignFirstResponder is not working. I am not sure why? I have tried to call it from textFieldDidEndEditing and nothing happens. A NIB is being used and each's delegate is pointing to files owner.
What needs to be done to get the keyboard to dismiss?
Thanks.
Don't use -textFieldDidEndEditing. That's called after the text field resigns firstResponder status, which is what you're trying to use it as a hook to make happen. Cart before horse, chicken-and-egg kind of problem.
Instead use -textFieldShouldReturn to get triggered when the return key is pressed (and remember to return YES; from that.) Also float a clear custom button behind the elements of the view and handle a "background tap" that goes through all the text fields on your view and resigns first responder on the lot of them.
actually you should return NO so that the text field does not begin editing at all. If it does, the firstresponder gets set and the keyboard pops up again.
Make sure your setting your delegates for the textfield.
myTextField.delegTe = self;
And you are using in your header:
<UITextFieldDelegate>
EDIT:
Try:
if(textField == myTextField){
[textField resignFirstResponder];
}

Hiding keyboard when clear button is pressed in UITextField

Is there any way to hide the keyboard when a clear button of UITextField is pressed?
Yes, there is, although I suspect that doing so would violate the Apple Human Interface Guidelines.
To do so, add the following method to your view controller's implementation file. Then make the view controller into your textfield's delegate.
- (BOOL) textFieldShouldClear:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
The downside to this approach is if you ever want to prevent the textfield from clearing, your code becomes messy. Instead you might try to define a custom method and then connect it to the valueDidChange method and check for an empty value.
-(IBAction)hideKeyboardFromTextField:(id)sender{
//TODO: Check if the previous value was longer than one character to differentiate
//between backspace and clear.
//check if the editing caused the box to be empty
if([[sender value] isEqualToString:#""] || [sender value] == nil)
[sender resignFirstResponder];
}
}
The problem here is that you can't easily differentiate between a tap on the clear button and a tap on the delete button when there is one character in the UITextField.
As I said in the beginning of my answer, this is not advisable in the first place and as the answers here have shown, it is not so easy to implement. I don't think it's worth the hassle, considering the difficulty involved and the fact that it doesn't result in optimal user experience.
This code is definitely working for me to hide the key board while clearing out the content of the textfield
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
textField.text = #"";
return NO;
}
Yep. Call resignFirstResponder on the text field in the delegate's textFieldShouldClear: method.
In UITextFieldDelegate
- (BOOL)textFieldShouldClear:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
But there is a problem with this. From the manual, "The text field calls this method in response to the user pressing the built-in clear button. (This button is not shown by default but can be enabled by changing the value in the clearButtonMode property of the text field.) This method is also called when editing begins and the clearsOnBeginEditing property of the text field is set to YES."
Note that, this method is called when editing begins if clearsOnBeginEditing is set to YES. So if you call resignFirstResponder in this method then editing will not begin actually. So you need to set clearsOnBeginEditing to NO. Obviously then the text field won't be cleared when editing begins.
Another IMPORTANT matter not directly related to the question. Hiding the keypad after tapping clear button is not a familiar behavior and Apple does NOT like changing the behavior of standard items. You may get a rejection for this.
Try this code:
[TextField performSelector:#selector(resignFirstResponder) withObject:nil afterDelay:0.1];
For Swift
In your UITextFieldDelegate
func textFieldShouldClear(_ textField: UITextField) -> Bool {
textField.resignFirstResponse()
return true
}

Focus on next valid key view on iPhone

Is there an iPhone equivalent for the NSResponder methods -selectNextKeyView or -nextValidKeyView from Mac OS X? I know about the -becomeFirstResponder method, but finding out which view to call that on is not very pretty when view hierarchies get more complicated.
There must be some kind of way to find this out as when I press tab when in the iPhone Simulator, focus does properly go to the next UITextField. This made me wonder what exactly happens when I press tab. Any ideas?
Update: This does exactly what I want, but _nextKeyResponder is private API, so a no-no. Is there any way to do a 'fake' tab key press without using private API?
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
// Try to find next responder
UIView *nextResponder = (UIView *)[self.view _nextKeyResponder];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
[self.tableView scrollRectToVisible:[self.tableView convertRect:[nextResponder frame] fromView:nextResponder] animated:YES];
} else {
// Not found, so remove keyboard.
[textField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
There is not a public iOS equivalent for NSResponder's -selectKeyView or -nextValidKeyView.
When the first responder is an instance of UITextField, pressing tab instantiates a private subclass of UIEvent which is passed to -[UIApplication sendEvent:], which in turn calls -[UIView _nextKeyResponder].
-[UIView _nextKeyResponder] doesn't work quite the way you think it does. It treats the key view chain as a loop, so your else block will never be reached. For the same reason, even if there was a public API for synthesizing keyboard events, you probably wouldn't want to use it.
Instead, you probably want something more like UIWebView's UIToolbar-based form input accessory. Its buttons can be enabled and disabled when appropriate, and its delegate handles the actual button press actions.
To implement such a delegate in a general way, however, it might be helpful to look at how -[UIView _nextKeyResponder] is implemented.
In the UITextField delegate -textFieldDidEndEditing:, switch between the various text fields (for example, by testing the text field's tag property).
When you match one text field, set another text field or other control to become the next responder.
I'm surprised nobody else appears to have solved this on iOS.
I devised a solution that handles both Tab and Shift+Tab to go forward and backward to any field you want on iOS, and doesn't use any private APIs.
Here is the write-up: http://weaklyreferenced.wordpress.com/2012/11/13/responding-to-the-tab-and-shift-tab-keys-on-ios-5-ios-6-with-an-external-keyboard/

Hide keyboard when losing focus off UISearchBar

I'm not sure why this is so hard. I have a UISearchBar at the top of my page. When the user types into that UISearchBar, it will automatically filter the results in the UITableView that is below the search bar. There is no need for a Search button since I search when keys are pressed.
The flow of the application is that the user types a search in the search bar (with the keyboard being displayed) and then will scroll the results in the table view - at which point the keyboard needs to disappear.
I'm having a hard time getting the keyboard to disappear.
I know I need to do:
[searchBar resignFirstResponder];
to get the keyboard to disappear but I can't find what delegate I need to perform this on. I want to do this as soon as the user touches the table view.
Any ideas?
Try this:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[searchBar resignFirstResponder];
}
It worked for me
I think the easiest (and best) way to do this is to subclass your global view and use hitTest:withEvent method to listen to any touch. Touches on keyboard aren't registered, so hitTest:withEvent is only called when you touch/scroll/swipe/pinch... somewhere else, then call [self endEditing:YES].
This is better than using touchesBegan because touchesBegan are not called if you click on a button on top of the view. It is also better than using a dim screen because in a complexe and dynamic user interface, you can't put dim screen every where. Also, it's better than calling [searchBar resignFirstResponder], because you may have many text fields on screen, so this works for all of them.
You might want to do it as Cydia (jailbroken packaging UI) does it - there is a search button, and when you press the search button, it closes the keyboard. The results are still filtered as you type for a preview.
Since the results are going to be in a table view, use UIScrollView's delegate (to which UITableView responds) method - (void)scrollViewDidScroll:(UIScrollView *)scrollView.
You'll need to have your view controller respond to the UITableView's data source and delegate (in the .h file):
<UITableViewDataSource, UITableViewDelegate>
Than in your initialization method in the .m file add:
self.tableView.dataSource = self;
self.tableView.delegate = self;
Finally, add this method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self.view endEditing:YES];
}
This will make the UISearchBar lose focus, and the keyboard will hide.
One possibility is that the UISearchBar belongs to a controller, that is displayed in UIModalPresentationFormSheet.
I had the same problem and found out that this is related to the method "disablesAutomaticKeyboardDismissal" of UIViewController.
The Apple documentation states the following:
Override this method in a subclass to allow or disallow the dismissal
of the current input view (usually the system keyboard) when changing
from a control that wants the input view to one that does not. Under
normal circumstances, when the user taps a control that requires an
input view, the system automatically displays that view. Tapping in a
control that does not want an input view subsequently causes the
current input view to be dismissed but may not in all cases. You can
override this method in those outstanding cases to allow the input
view to be dismissed or use this method to prevent the view from being
dismissed in other cases.
The default implementation of this method returns YES when the modal
presentation style of the view controller is set to
UIModalPresentationFormSheet and returns NO for other presentation
styles. Thus, the system normally does not allow the keyboard to be
dismissed for modal forms.
In my case, I displayed the search bar within the navigation bar, so I had to create a subclass of UINavigationViewController that overrides the method as follows:
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
After that resignFirstResponder would finally make the keyboard disappear.
Might be super late to answer but this might help anyone in future. This particular piece of code worked for me. P.S. I don't own this solution, found some time ago on the net itself.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if ([self.srchBar isFirstResponder] && [touch view] != self.srchBar)
{
[self.srchBar resignFirstResponder];
}
[super touchesBegan:touches withEvent:event];
}
Given a view with a searchBar variable, add this method to the view:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
{
if searchBar.isFirstResponder && !searchBar.point(inside: point, with: event){
searchBar.resignFirstResponder()
}
return super.hitTest(point, with: event)
}