xcode storyboard Container View - How do I access the viewcontroller
Solution 1
There is another solution by specifying an identifier for the embed segue(s) and retrieve the corresponding view controllers in method prepareForSegue:
The advantage of this way is that you needn't rely on a specific order in which your child view controllers are added due to the fact that each child view controller is embedded via an unique segue identifier.
Update 2013-01-17 - Example
- (void) prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
// -- Master View Controller
if ([segue.identifier isEqualToString:c_SegueIdEmbedMasterVC])
{
self.masterViewController = segue.destinationViewController;
// ...
}
// -- Detail View Controller
else if ([segue.identifier isEqualToString:c_SegueIdEmbedDetailVC])
{
self.detailViewController = segue.destinationViewController;
// ...
}
}
c_SegueIdEmbedMasterVC
& c_SegueIdEmbedDetailVC
are constants with the corresponding ID of the segue IDs defined in the storyboard.
Solution 2
When you add a container view the xcode calls the UIViewController method addChildViewController:
In your case, you can get the container ViewController looking for it on the SplashViewController's list of childViewControllers
, something like this:
for (UIViewController *childViewController in [self childViewControllers])
{
if ([childViewController isKindOfClass:[InstallViewController class]])
{
//found container view controller
InstallViewController *installViewController = (InstallViewController *)childViewController;
//do something with your container view viewcontroller
break;
}
}
I had the same doubt yesterday :)
Solution 3
The answer of Vitor Franchi is correct but could be more performant and convenient. Especially when accessing the child view controller several times.
Create a readonly property
@interface MyViewController ()
@property (nonatomic, weak, readonly) InstallViewController *cachedInstallViewController;
@end
Then create a convenient getter method
- (InstallViewController *)installViewController
{
if (_cachedInstallViewController) return _cachedInstallViewController;
__block InstallViewController *blockInstallViewController = nil;
NSArray *childViewControllers = self.childViewControllers;
[childViewControllers enumerateObjectsUsingBlock:^(id childViewController, NSUInteger idx, BOOL *stop) {
if ([childViewController isMemberOfClass:InstallViewController.class])
{
blockInstallViewController = childViewController;
*stop = YES;
}
}];
_cachedInstallViewController = blockInstallViewController;
return _cachedInstallViewController;
}
From now on access the child view controller that way
[self.installViewController doSomething];
Comments
-
Justin808 almost 4 years
I'm trying to use storyboard and get things working properly. I've added a a Container View to one of my existing views. When I try to add a reference to this in my view controller
.h
file (ctrl-drag), I get aIBOutlet UIView *containerView
. How do I get a reference to the container view's view controller instead? I need the container view controller so I can set it's delegate to my view's controller so they can "talk" to each other.I have my story board setup as:
And its referenced in my .h file as:
Notice in the .h that is is a UIView, not my InstallViewController for the view. How do I add a reference to the view controller? I need to be able to set its delegate.
-
Pantelis Proios over 11 yearsI am trying to do something similar and what i don't get is the "vc" in InstallViewController *installViewController = (InstallViewController *)vc;
-
DAXaholic over 11 yearsSorry for the late update. I'm sure you managed the problem by yourself in the meantime but eventually the example code helps other ones in the future.
-
vfranchi about 11 yearsYou are right, it should've been "childViewController". I've just fixed in the post. Sorry for taking that much to reply.
-
Yariv Nissim about 11 yearsGod answer. I Tried that trick before, and only after reading this answer I realized that it only works if you setup Segue Identifiers. However I would use isKindOfClass: instead.
-
Javier Quevedo about 11 yearsThis approach feels a bit like a "workaround" to me. Doesn't it?
-
vfranchi almost 11 yearsWell, it did the trick :) Does the prepareForSegue method is called when a Container View is added to another view?
-
jab over 10 yearsI'm not sure I like making that assumption, but it's useful to know.
-
silvansky about 10 yearsThat's not the universal way: view hierarchy can change and this method won't work.
-
shim almost 10 yearsWhy are there two view controllers (detail and master)? Isn't it just the one view controller in the container? What other segue are you referring to?
-
DAXaholic almost 10 years@shim: In my example project I had a kind of split view with a master and a detail view controller hosted in 2 separate container views - therefore the two view controllers.
-
Robert almost 10 yearsIts a shame that this is the best way of getting a reference to the child view controller. The whole point of the storyboards is to reduce boilerplate code like this. I could add the child view controller in
viewDidLoad
in fewer lines of code and it would be more maintainable than this. Anyone know if this fixed in XCode 6?