Find View that is the firstresponder

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;

    . . .

There is no simple way to find firstResponder in iOS. The answers above are only tracking UIViews 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).


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