How to Get Uiviewcontroller of a Uiview's Superview in iOS

How to get UIViewController of a UIView's superview in iOS?

You can't access it directly, but you can find the next view controller (if any) by traversing the responder chain.

This is how the Three20 framework does it:

- (UIViewController*)viewController
{
for (UIView* next = [self superview]; next; next = next.superview)
{
UIResponder* nextResponder = [next nextResponder];

if ([nextResponder isKindOfClass:[UIViewController class]])
{
return (UIViewController*)nextResponder;
}
}

return nil;
}

Given a view, how do I get its viewController?

Yes, the superview is the view that contains your view. Your view shouldn't know which exactly is its view controller, because that would break MVC principles.

The controller, on the other hand, knows which view it's responsible for (self.view = myView), and usually, this view delegates methods/events for handling to the controller.

Typically, instead of a pointer to your view, you should have a pointer to your controller, which in turn can either execute some controlling logic, or pass something to its view.

Get to UIViewController from UIView?

Since this has been the accepted answer for a long time, I feel I need to rectify it with a better answer.

Some comments on the need:

  • Your view should not need to access the view controller directly.
  • The view should instead be independent of the view controller, and be able to work in different contexts.
  • Should you need the view to interface in a way with the view controller, the recommended way, and what Apple does across Cocoa is to use the delegate pattern.

An example of how to implement it follows:

@protocol MyViewDelegate < NSObject >

- (void)viewActionHappened;

@end

@interface MyView : UIView

@property (nonatomic, assign) MyViewDelegate delegate;

@end

@interface MyViewController < MyViewDelegate >

@end

The view interfaces with its delegate (as UITableView does, for instance) and it doesn't care if its implemented in the view controller or in any other class that you end up using.

My original answer follows: I don't recommend this, neither the rest of the answers where direct access to the view controller is achieved

There is no built-in way to do it. While you can get around it by adding a IBOutlet on the UIView and connecting these in Interface Builder, this is not recommended. The view should not know about the view controller. Instead, you should do as @Phil M suggests and create a protocol to be used as the delegate.

How does one access a super's view controller?

In your secondary controller, try

id mainViewController = [self.view.superview nextResponder];

and check if this is the view controller you're looking for.

Apple's documentation of -[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)

How to get a UIViewController from a UIView via code

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)"

How to access ParentViewController method from subview?

May be this will return what you want to get:

 id mainViewController = [self.view.superview nextResponder];

Apple's documentation of -[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)

Other than this you can have idea from here.

Get superView of custom class

For your specific case, you can use [self.superView isMemberOfClass:[UITableViewCell class]] to check if your custom view is inside a table view cell, which (unless you are using tableViewCell in an unusual way!) means that it's being called from a UITableViewController.

More generally, if you wanted to find out the containing view controller, you can recursively walk up the responder chain to find the containing viewController as in the second answer in this post:
Get to UIViewController from UIView?

It's also important to note that there is a difference between isKindOfClass: and isMemberOfClass:

  • isKindOfClass returns YES if 'the receiver is an instance of given class or an instance of any class that inherits from that class.'

  • isMemberOfClass returns YES if ' the receiver is an instance of a given class.'

Therefore, your UITableViewController, which inherits from UIViewController, will answer YES to isKindOfClass:[UIViewController class], will your if statement to act unexpectedly. (Though in the example it also didn't work correctly because you still needed to walk up the responder chain further).

So, if you in fact are comparing a UIViewController to a UITableViewController use -isMemberOfClass and your logic in the example would work as expected.

How to list out all the subviews in a uiviewcontroller in iOS?

You have to recursively iterate the sub views.

- (void)listSubviewsOfView:(UIView *)view {

// Get the subviews of the view
NSArray *subviews = [view subviews];

for (UIView *subview in subviews) {

// Do what you want to do with the subview
NSLog(@"%@", subview);

// List the subviews of subview
[self listSubviewsOfView:subview];
}
}


Related Topics



Leave a reply



Submit