9

There is a way to get a view controller reference from a UIView object? I need something like this:

MyParentViewController *myParentViewController = [self.view.superview controller];
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
reinaldoluckman
  • 6,317
  • 8
  • 42
  • 50

5 Answers5

16

You can use the -nextResponder method to do it. According to http://developer.apple.com/library/ios/documentation/uikit/reference/UIResponder_Class/Reference/Reference.html#//apple_ref/occ/instm/UIResponder/nextResponder , "UIView implements this method by returning the UIViewController object that manages it (if it has one) or its superview (if it doesn’t)"

user102008
  • 30,736
  • 10
  • 83
  • 104
  • 4
    This is a nice workaround but views should never have the need to access their controller directly. That's why we have delegates. – Sulthan Feb 28 '14 at 11:10
5

UIView does not have reference to UIViewController by default.You can add it to your UIView subclass and set it when you create UIView in UIViewController.

If you are looking for parent of the viewcontroller, each UIViewController has property parentViewController, but if you want to access this from UIView you need to first get to your UIViewController.

You can see example how to create reference to your UIViewController in your subclass of UIView and how/where to set it up in View Controller Programming guide for iPhone, see section Creating the View Programmatically in Defining a Custom View Controller Class, here is the example, for more details see the linked Metronome example.

 - (void)loadView {

    self.wantsFullScreenLayout = YES;

    MetronomeView *view = [[MetronomeView alloc]
                          initWithFrame:[UIScreen mainScreen].applicationFrame];
    view.metronomeViewController = self;
    self.view = view;
    self.metronomeView = view;

    [view release];
}

In header:

@interface MetronomeView : UIView {
    MetronomeViewController *metronomeViewController;
...
stefanB
  • 77,323
  • 27
  • 116
  • 141
2

You can use

[(MyParentViewController *)[[self.view superview] nextResponder] doSomething];
codercat
  • 22,873
  • 9
  • 61
  • 85
Upendar Gareri
  • 427
  • 1
  • 4
  • 14
  • Documentation says "UIView implements this method by returning the UIViewController object that manages it (if it has one) or its superview (if it doesn’t);". So if the view is nested deeply, nextResponder will simply return it's superview's superview (not a controller) and thus causing an error(unknown selector). On the other hand if the view is controller's view, it could return another controller (for example controller is in navigationController, so the controller's parent view is navigationController's view and nextResponder will return navigationController). So that's why I've downvoted – JakubKnejzlik May 23 '14 at 01:58
1

You shouldn't save the reference to the view controller as it may change dynamically. Traverse the responder chain every time you need it.

Rivera
  • 10,792
  • 3
  • 58
  • 102
1

You can use the following:

    UIViewController* yourViewController = 
                      (UIViewController*)[(YourAppDelegate*)
                      [[UIApplication sharedApplication] delegate] viewController];
Rabi
  • 2,593
  • 1
  • 23
  • 26