You can access a view controller's parent with the parentViewController
property.
if([self.parentViewController isKindOfClass:[SomeViewController class]]) {
SomeViewController* viewController = (SomeViewController*)self.parentViewController;
[viewController foo];
}
However, this depends on the relationship between your view controllers. From your question, I inferred that you had a parent-child relationship with multiple children, though please correct me if I am wrong! This is very different from a modal view controller presentation, in which only one view controller is presented and it demands the user's immediate attention.
Explanation:
There seems to be some confusion about the difference between the parentViewController
and presentingViewController
properties on UIViewController. There are two different view controller relationships, each of which applying to one of these properties.
If you wish to add multiple view controllers' views as subviews of a parent view controller, you use view controller containment. In this situation, any of the views added as subviews (children) of the parent view controller will return the parent view controller (which controls the superview of the children; the parent view) when the parentViewController
property is accessed. In this situation, the presentingViewController
property returns null
.
For example, in the parent view controller:
- (void)viewDidLoad {
[super viewDidLoad];
SomeViewController* someVC = [[SomeViewController alloc] init];
[self addChildViewController:someVC];
[self.view addSubview:someVC.view];
[someVC.view setFrame:<SOME_FRAME>];
[someVC didMoveToParentViewController:self];
AnotherViewController* anotherVC = [[AnotherViewController alloc] init];
[self addChildViewController:anotherVC];
[self.view addSubview:anotherVC.view];
[anotherVC.view setFrame:<ANOTHER_FRAME>];
[anotherVC didMoveToParentViewController:self];
/* this prints self */
NSLog(@"%@", someVC.parentViewController);
/* this prints null */
NSLog(@"%@", someVC.presentingViewController);
/* this prints self */
NSLog(@"%@", anotherVC.parentViewController);
/* this prints null */
NSLog(@"%@", anotherVC.presentingViewController);
}
Contrarily, if you simply wish to present a single, modal view controller (a situation which is more common than the one-to-many parent-child relationship above), then the presentingViewController
property is used.
For example, in the presenting view controller:
- (void)someActionTriggered {
SomeViewController* viewController = [[SomeViewController alloc] init];
[self presentViewController:viewController animated:YES completion:nil];
/* this prints null */
NSLog(@"%@", viewController.parentViewController);
/* this prints self, or a tab bar controller if 'self' is contained in one */
NSLog(@"%@", viewController.presentingViewController);
}
Although presentingViewController
might be seen more commonly due to the prevalence of the modal view controller pattern in iOS, the view controller containment parent-child relationship of view controllers is absolutely legitimate, and the parentViewController
and childViewController
properties of a UIViewController have not been deprecated as of iOS 5, their use has just changed. You can read this excerpt from the documentation:
Discussion
If the recipient is a child of a container view controller, this property holds the view controller it is contained in. If the recipient has no parent, the value in this property is nil.
Prior to iOS 5.0, if a view did not have a parent view controller and was being presented, the presenting view controller would be returned. On iOS 5, this behavior no longer occurs. Instead, use the presentingViewController property to access the presenting view controller.