1

Here's a ViewController, and it has a container view. Note the container is only a part of the fullscreen, as usual.

enter image description here

So the container contains the VC on the right. It could be, say, "Parts" showing the Parts list.

But what if I have say four VCs, I want to put in that area (where the container is). Maybe: Parts, Tires, Brakes, Oils.

Of course, only one will show at a time, on that area.

What the heck is the best way to really do that?

In the past I've made four container views (in the exact same location and size) and just brought up the one I wanted, and manually removed the other three.

What is the proper solution here???

Note -- a related question is, indeed, can a container view in fact point to more than one VC ?? (In that way you could still swap "manually", it would just be much easier to need only one, not five matching, container views.)

Finally here's a related essay found on the www ...

http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers

Fattie
  • 27,874
  • 70
  • 431
  • 719

2 Answers2

3

You have - as expected - several options.

Option 1 Use a UIPageViewController. You can then even swipe between the different child view controllers and they will only be loaded when they are needed.

You have to set the UIPageViewController's dataSource to an object that implements at least these two methods:

#pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
      viewControllerBeforeViewController:(UIViewController *)viewController
{
    // Return the viewController instance _before_ the given viewController or nil when there are no more view controllers to display.

    return nil;
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
       viewControllerAfterViewController:(UIViewController *)viewController
{
    // Return the viewController instance _after_ the given viewController or nil when there are no more view controllers to display.

    return nil;
} 

Option 2 Create an outlet for your container view and then programmatically add/remove the child view controller you want to display, like so:

- (void)setCurrentChildViewController:(UIViewController *)viewController
{
    // Remove existing child
    if (self.currentChildViewController) {
        if (self.currentChildViewController.isViewLoaded) {
            [self.currentChildViewController.view removeFromSuperview];
        }
        [self.currentChildViewController willMoveToParentViewController:nil];
        [self.currentChildViewController removeFromParentViewController];
    }

    // Now add viewController as child
    [self addChildViewController:viewController];
    [viewController didMoveToParentViewController:self];
    viewController.view.frame = self.containerView.bounds;
    viewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

    [self beginAppearanceTransition:YES animated:NO];
    [self.containerView addSubview:viewController.view];
    [self endAppearanceTransition];

    self.currentChildViewController = viewController;
}

Option 3 Hide and show the child view controllers as you have described in your question, but I'd rather pick option 1 or 2, depending on your needs.


Footnote for beginners:

With Storyboards, when you load a UIViewController, you often need to use instantiateViewControllerWithIdentifier:, so, a simple example

SomeViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"someViewControllerStoryboardID"];
// see method created in option 2
[self setCurrentChildViewController:vc];
Johannes Fahrenkrug
  • 42,912
  • 19
  • 126
  • 165
  • Holy crap! I never thought of a UIPageViewController, thanks! is it true that it is tricky to NOT have it swipe? (Eg, http://stackoverflow.com/a/24847685/294884 ) I would only want it to change, when I say so... you think? Thanks again! – Fattie Aug 28 '14 at 15:11
  • Re programmatically adding/removing the child view. (that is great sample code BTW, thank you.) It seems fraught with problems .. I found I had to write a whole VC subclass for handling it neatly you know? I actually found, using scheme 3, it's really best to make a whole new VC "multi holder container VC!" which HOLDS your 4 or 5 VCs, otherwise it's just a mess. I'm amazed there is no super-easy solution for this. I'm gonna go try your astounding UIPageViewController idea... – Fattie Aug 28 '14 at 15:30
  • @JoeBlow Thanks! Manually adding/removing child VCs works pretty well, but UIPageViewController works well, too. To disable swiping, check this out: http://stackoverflow.com/a/24847685/171933 – Johannes Fahrenkrug Aug 28 '14 at 18:11
  • I added a minor tip for "beginners" (err - I did not get caught out by this for hours, or anything :) ) – Fattie Aug 29 '14 at 09:34
1

I used a segmented control with a containing scrollView.

The container view and segmented control are a subviews of the scrollView. When I press one of the tabs in the segmented control, I use the two method of removing a sub view controller, showing new subview controller, then I recalculate the height required for the newly loaded sub view controller and set the scrollView's autolayout height constraint constant to the new value.

Zhang
  • 11,549
  • 7
  • 57
  • 87
  • Hi Zhang! Indeed, that's what I do currently, as I say, just manually swap in and out, basically, VCs. I want to know the bad-ass way to do this! :) – Fattie Aug 28 '14 at 15:07