Get to UIViewController from UIView?

前端 未结 29 1735
一整个雨季
一整个雨季 2020-11-22 16:57

Is there a built-in way to get from a UIView to its UIViewController? I know you can get from UIViewController to its UIView

相关标签:
29条回答
  • 2020-11-22 17:34

    Another easy way is to have your own view class and add a property of the view controller in the view class. Usually the view controller creates the view and that is where the controller can set itself to the property. Basically it is instead of searching around (with a bit of hacking) for the controller, having the controller to set itself to the view - this is simple but makes sense because it is the controller that "controls" the view.

    0 讨论(0)
  • 2020-11-22 17:35

    The simplest do while loop for finding the viewController.

    -(UIViewController*)viewController
    {
        UIResponder *nextResponder =  self;
    
        do
        {
            nextResponder = [nextResponder nextResponder];
    
            if ([nextResponder isKindOfClass:[UIViewController class]])
                return (UIViewController*)nextResponder;
    
        } while (nextResponder != nil);
    
        return nil;
    }
    
    0 讨论(0)
  • 2020-11-22 17:36

    While these answers are technically correct, including Ushox, I think the approved way is to implement a new protocol or re-use an existing one. A protocol insulates the observer from the observed, sort of like putting a mail slot in between them. In effect, that is what Gabriel does via the pushViewController method invocation; the view "knows" that it is proper protocol to politely ask your navigationController to push a view, since the viewController conforms to the navigationController protocol. While you can create your own protocol, just using Gabriel's example and re-using the UINavigationController protocol is just fine.

    0 讨论(0)
  • 2020-11-22 17:36

    If your rootViewController is UINavigationViewController, which was set up in AppDelegate class, then

        + (UIViewController *) getNearestViewController:(Class) c {
    NSArray *arrVc = [[[[UIApplication sharedApplication] keyWindow] rootViewController] childViewControllers];
    
    for (UIViewController *v in arrVc)
    {
        if ([v isKindOfClass:c])
        {
            return v;
        }
    }
    
    return nil;}
    

    Where c required view controllers class.

    USAGE:

         RequiredViewController* rvc = [Utilities getNearestViewController:[RequiredViewController class]];
    
    0 讨论(0)
  • 2020-11-22 17:38

    I would suggest a more lightweight approach for traversing the complete responder chain without having to add a category on UIView:

    @implementation MyUIViewSubclass
    
    - (UIViewController *)viewController {
        UIResponder *responder = self;
        while (![responder isKindOfClass:[UIViewController class]]) {
            responder = [responder nextResponder];
            if (nil == responder) {
                break;
            }
        }
        return (UIViewController *)responder;
    }
    
    @end
    
    0 讨论(0)
  • 2020-11-22 17:39

    I don't think it's "bad" idea to find out who is the view controller for some cases. What could be a bad idea is to save the reference to this controller as it could change just as superviews change. In my case I have a getter that traverses the responder chain.

    //.h

    @property (nonatomic, readonly) UIViewController * viewController;
    

    //.m

    - (UIViewController *)viewController
    {
        for (UIResponder * nextResponder = self.nextResponder;
             nextResponder;
             nextResponder = nextResponder.nextResponder)
        {
            if ([nextResponder isKindOfClass:[UIViewController class]])
                return (UIViewController *)nextResponder;
        }
    
        // Not found
        NSLog(@"%@ doesn't seem to have a viewController". self);
        return nil;
    }
    
    0 讨论(0)
提交回复
热议问题