31

I want to add a tableViewController as a child view controller of a containerViewController (shown below). According to Apple's View Controller Programming Guide I can achieve this by the following lines of code inside my containerViewController:

   [self addChildViewController:tableViewController];
   [self.view addSubview:tableViewController.view];
   [tableViewController didMoveToParentViewController:self];

In fact, that works fine. Now the problem is that I do not want to add the tableViewController's view as a subview of the containerViewController's root view. Instead I want to add it as a subview of the containerView (see image) which itself is a subview of the containerViewController's root view. So I changed the above code as follows:

   [self addChildViewController:tableViewController];
   [self.contentView addSubview:tableViewController.view];
   [tableViewController didMoveToParentViewController:self];

Now when I launch the app it crashes immediately with this error:

Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller: should have parent view controller: but actual parent is:'

What is the problem here? Is it not possible to add a childViewController's view to a specific sub view of its containerViewController? Or how can I achieve this without an error in the view controller hierarchy?

containerViewController

Mischa
  • 15,816
  • 8
  • 59
  • 117

3 Answers3

49

It doesn't really matter which view you are adding the child viewController to. If a view of a viewController is added to another viewController you need set it properly.

tableViewController.view.frame = self.contentView.bounds;
[self.contentView addSubview:tableViewController.view];
/*Calling the addChildViewController: method also calls 
the child’s willMoveToParentViewController: method automatically */
[self addChildViewController:tableViewController];
[tableViewController didMoveToParentViewController:self];

Source code

alexburtnik
  • 7,661
  • 4
  • 32
  • 70
Anupdas
  • 10,211
  • 2
  • 35
  • 60
  • Are you sure about that and have you tested that code? I have tried that and it *does* make a difference whether you add the childViewController's view to the root view of the containerViewController or to any of its subviews. – Mischa Jun 09 '13 at 18:38
  • 4
    +1 for tableViewController.view.frame = self.contentView.bounds; – onmyway133 Dec 24 '13 at 01:53
  • 7
    Following Apple docs, you don't need to call 'willMoveToParentViewController:' by yourself: it's automatically called when you call 'addChildViewController:'. Code above can lead to situation, when 1st method will be called twice. – Oleksandr Palii Jan 13 '14 at 07:20
  • @Anupdas, I couldn't find `self.contentView`, I want to do it programmatically, I guess, you're adding a view named `contentView` right? – Hemang Dec 22 '14 at 05:57
  • @Hemang I quoted from the OP's requirement, yes you need to create a container view to hold the child view controller. – Anupdas Dec 22 '14 at 07:48
  • @Anupdas, Thanks for the reply. However I don't need to create a container view. I just question/answer my self here. http://stackoverflow.com/q/27598846/1603234 – Hemang Dec 22 '14 at 08:14
  • 1
    I think you have to add the childViewController before calling addSubView on the childViewController's view – Madhan Apr 06 '15 at 19:43
  • This line did it for me: "tableViewController.view.frame = self.contentView.bounds". I had " = self.contentView.frame" instead. – Danilo Carvalho May 14 '17 at 05:30
1
//class name InfoViewController

IBOutlet UIView *addViewToAddPlot;
InfoViewController *InfoController;

-(void) add_method
{
    InfoController = [[InfoViewController alloc] initWithNibName:@"InfoViewController" bundle:nil];
    InfoController.view.frame = self.addViewToAddPlot.bounds;

    [self containerAddChildViewController:InfoController];
}

-(void) remove_method
{
    [self containerRemoveChildViewController : InfoController];
}

- (void)containerAddChildViewController:(UIViewController *)childViewController {

    [self addChildViewController:childViewController];
    [self.addViewToAddPlot addSubview:childViewController.view];
    [childViewController didMoveToParentViewController:self];

}

- (void)containerRemoveChildViewController:(UIViewController *)childViewController {

    [childViewController willMoveToParentViewController:nil];
    [childViewController.view removeFromSuperview];
    [childViewController removeFromParentViewController];

}

Add and remove viewcontroller ,#childviewcontroller

Manjeet
  • 101
  • 9
1

To show a child_view_controller over a main_view_controller.

step 1: create a main_view_controller in storyboard.

step 2: create a child_view_controller with a UIview and some Label inside in storyboard.

step 3: in main_view_controller's button action add the following code:

- (IBAction)YourButtonAction:(id)sender {
    ChildViewControllerName *childViewControllerName = [self.storyboard instantiateViewControllerWithIdentifier:@"storyboardIdYouProvided"];
    childViewControllerName.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
    [self.view addSubview:childViewControllerName.view];
    [childViewControllerName didMoveToParentViewController:self];
}
Ram Madhavan
  • 2,362
  • 1
  • 17
  • 20