Given a view, how do I get its viewController?

后端 未结 13 609
北海茫月
北海茫月 2020-11-28 02:00

I have a pointer to a UIView. How do I access its UIViewController? [self superview] is another UIView, but not the

相关标签:
13条回答
  • 2020-11-28 02:54

    From the UIResponder documentation for nextResponder:

    The UIResponder class does not store or set the next responder automatically, instead returning nil by default. Subclasses must override this method to set the next responder. UIView implements this method by returning the UIViewController object that manages it (if it has one) or its superview (if it doesn’t); UIViewController implements the method by returning its view’s superview; UIWindow returns the application object, and UIApplication returns nil.

    So, if you recurse a view’s nextResponder until it is of type UIViewController, then you have any view’s parent viewController.

    Note that it still may not have a parent view controller. But only if the view has not part of a viewController’s view’s view hierarchy.

    Swift 3 and Swift 4.1 extension:

    extension UIView {
        var parentViewController: UIViewController? {
            var parentResponder: UIResponder? = self
            while parentResponder != nil {
                parentResponder = parentResponder?.next
                if let viewController = parentResponder as? UIViewController {
                    return viewController
                }
            }
            return nil
        }
    }
    

    Swift 2 extension:

    extension UIView {
        var parentViewController: UIViewController? {
            var parentResponder: UIResponder? = self
            while parentResponder != nil {
                parentResponder = parentResponder!.nextResponder()
                if let viewController = parentResponder as? UIViewController {
                    return viewController
                }
            }
            return nil
        }
    }
    

    Objective-C category:

    @interface UIView (mxcl)
    - (UIViewController *)parentViewController;
    @end
    
    @implementation UIView (mxcl)
    - (UIViewController *)parentViewController {
        UIResponder *responder = self;
        while ([responder isKindOfClass:[UIView class]])
            responder = [responder nextResponder];
        return (UIViewController *)responder;
    }
    @end
    

    This macro avoids category pollution:

    #define UIViewParentController(__view) ({ \
        UIResponder *__responder = __view; \
        while ([__responder isKindOfClass:[UIView class]]) \
            __responder = [__responder nextResponder]; \
        (UIViewController *)__responder; \
    })
    
    0 讨论(0)
提交回复
热议问题