Find View that is the firstresponder
Solution 1
All I had to do was
@implementation UIView (FindViewThatIsFirstResponder)
- (UIView *)findViewThatIsFirstResponder
{
if (self.isFirstResponder) {
return self;
}
for (UIView *subView in self.subviews) {
UIView *firstResponder = [subView findViewThatIsFirstResponder];
if (firstResponder != nil) {
return firstResponder;
}
}
return nil;
}
@end
Solution 2
Use UIControl as a root reference to different types of control that can become first responder.
UIControl *currentControl;
As Gobot says - whenever a textfield becomes first responder, keep a note of which one it is...
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
currentControl = textField;
. . .
Solution 3
There is no simple way to find firstResponder
in iOS. The answers above are only tracking UIView
s but all subclasses of UIResponder
such as UIViewController
can be a first responder.
According to the Quick Help
of UIResponder
:
Many key objects are also responders, including the UIApplication object, UIViewController objects, and all UIView objects (which includes UIWindow). As events occur, UIKit dispatches them to your app's responder objects for handling.
And the only way to follow UIResponder
chain will be using UIResponder
's next: UIResponder
property.
Returns the next responder in the responder chain, or nil if there is no next responder. The UIResponder class does not store or set the next responder automatically, so this method returns nil by default. Subclasses must override this method and return an appropriate next responder. For example, UIView implements this method and returns the UIViewController object that manages it (if it has one) or its superview (if it doesn’t). UIViewController similarly implements the method and returns its view’s superview. UIWindow returns the application object. UIApplication returns nil.
In the most UIKit
object superview
, UIViewController
, UIWindow
, UIApplication
or Appdelegate
will be the next
UIResponder
.
extension UIResponder {
func findFirstResponder() -> UIResponder? {
var responder: UIResponder? = self
while responder != nil {
guard let r = responder, r.isFirstResponder else {
responder = responder?.next
continue
}
return r
}
return nil
}
}
However the above doesn't track responder
's siblings. I guess if you really want to track them all, you need to check the type of responder and track its child(subview, child view controller).
Armand
I have been a professional software developer for 11 years. I mostly work with .NET based technologies building web applications with various JavaScript frameworks. I love working on new and exiting projects irrespective of the industry the project is built for. Besides programming I am an avid sport shooter, shooting in IDPA and IPSC competitions.
Updated on July 22, 2022Comments
-
Armand almost 2 years
I would like to get the view that is the first responder, currently I have a UITableView that contains UITextFields, using a method:
-(UIView*) findFirstResponder { }
I would like to be able to get the view that is the firstResponder and then do something with that view.
Any ideas?
-
o15a3d4l11s2 over 12 yearsDon't you need the textField itself? What is the relation between the subview and the table with the textFields?
-
Armand over 12 yearsTo go into more detail of why this will work for me: I have a UITextField that has a UIPickerView as a inputView, now these are all created dynamically so I don't hold any reference to any fields except my table view, so when I select a textfield the UIPickerView will show up and I then select a value in the picker to set the text of the UITextField, I then had to call a delegate method to pass the selected value back to the current firstresponder. see this question stackoverflow.com/questions/9874037/…
-
taylorcressy about 10 yearsSheesh, all these other solutions are ridiculous. This should be top answer on all the likewise questions :)
-
devios1 over 9 yearsWhat if the first responder is not a
UITextField
? There areUITextView
s too, and maybe others...? Don't get me wrong this is a fine solution for the question asked, but I'm looking for something a little more universal. -
Damo over 9 yearsYou could use a reference to UIControl. See above
-
Shantanu about 9 yearsThis is the best answer yet to any similar questions.
-
famfamfam almost 3 yearshow to called method "findFirstResponder"? Thanks