5

I have a container view set up in my storyboard file but I want to embed the view controller programatically after setting some properties. This is my code in the parent VC's viewDidLoad:

_workoutVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"entryTableVC"];
_workoutView = _workoutVC.tableView;

[self addChildViewController:_workoutVC];

[_workoutVC.tableView setFrame:_container.bounds];
[_container addSubview:_workoutView];

However, viewDidLoad in the child is not called at any time. When I run the simulator my container view is blank. I've checked in the debugger that none of my properties are nil.

circuitlego
  • 3,469
  • 5
  • 22
  • 22

7 Answers7

0

The viewDidLoad: method is called when the view property is accessed for the first time. I assume that in your case view == tableView. If not, you have to adjust the loadView method of your child VC.

- (void)loadView {
    //create your table view here
    //...
    self.view = self.tableView;
}

Then just use view property instead of tableView.

_workoutView = _workoutVC.view;

EDIT:

The full code would be:

_workoutVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"entryTableVC"];
_workoutView = _workoutVC.view;

[self addChildViewController:_workoutVC];

[_workoutView setFrame:_container.bounds];
[_container addSubview:_workoutView];
Adam
  • 26,549
  • 8
  • 62
  • 79
  • I tried your suggestion and it makes no difference. Neither loadView or viewDidLoad are called. – circuitlego Jul 29 '13 at 22:32
  • @circuitlego `loadView` should be called when you access `view` property. I have edited my answer but I don't know how your storyboard looks like. – Adam Jul 30 '13 at 15:14
0

If you aren't using an embed segue and are adding child view controllers manually, why use a container view at all? Try this:

_workoutVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"entryTableVC"];
_workoutView = _workoutVC.tableView;

[self addChildViewController:_workoutVC];

[_workoutVC.view setFrame:self.view.frame];
[self.view addSubview:_workoutVC.view];
JonahGabriel
  • 3,066
  • 2
  • 18
  • 28
0

I had a similar situation. I used a normal UIView in the container view controller (as opposed to the Xcode provided "Container View").

The sequence of events that I used is:

    ChildViewController *childViewController = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"ChildViewController"];
    childViewController.view.frame = self.viewForChildViewController.frame;
    self.viewForChildViewController = childViewController.view;
    [self.view addSubview:self.viewForChildViewController];

    [self addChildViewController:childViewController];
    [childViewController didMoveToParentViewController:self];

It's a bit of a dance but it allows me to programmatically set the child view controller and also insures that -viewDidLoad is called on the child view controller. Also, you should be able to set some properties after this.

Aaron A.
  • 311
  • 2
  • 5
0

(Swift 2) Since this question doesn't have an accepted answer...

What I ended up doing is create a convenience init at the child view controller:

convenience init() {
    self.init(nibName: "ChildViewController", bundle: nil)
    //initializing the view Controller form specified NIB file
}

and in the parentViewController's viewDidLoad():

let commentsView = CommentsViewController()
self.addChildViewController(commentsView)
self.momentsScrollView.addSubview(commentsView.view)
commentsView.didMoveToParentViewController(self)

I used a simple UIView not UIContainerView, but it's similar.

Andre Simon
  • 665
  • 10
  • 16
0

Sorry this is late but I just ran into this problem. It's one of those obscure problems with InterfaceBuilder, where occasionally it doesn't create complete information for custom classes, so the segue isn't finding the controller class.

In my case I had two identical views with embedded TableViewControllers. The first worked, the second didn't. When examining the Storyboard as source code I saw that the second was missing some extra information, when I added it, viewDidLoad was called. To fix this

1) Open your storyboard as source code.

2) Search to find the customClass for your embedded view controller

customClass="MyEmbeddedViewController"

2) Add the following values after it (MyAppProject should be the name of your project, target is just target).

customModule="MyAppProject" customModuleProvider="target"

Your embedded controller should now trigger viewDidLoad and work normally.

SafeFastExpressive
  • 3,637
  • 2
  • 32
  • 39
-1

"I want to embed the view controller programatically after setting some properties" --- You can't do that. If you have a container view, you automatically get a view controller embedded in it, and its viewDidLoad is called right before the parent controller's viewDidLoad. If you want to set some properties of the embedded controller, you can do that in prepareForSegue in the parent controller.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
-3

To anyone that might still have the same problem.

I had a similar situation and solved it by just calling loadView().

let sb: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewControllerWithIdentifier("LoadingView") as! LoadingViewController
controller.loadView()

I could then access everything inside the view.

Deivi Taka
  • 155
  • 2
  • 8
  • 2
    As documentation says, loadView() should never be called directly. https://developer.apple.com/reference/uikit/uiviewcontroller/1621454-loadview – Ramiro Oct 10 '16 at 14:49