1

I have an application that should show one of a set of different views depending on values reported by the accelerometer. I would like to set the views up in the Storyboard Editor in Xcode, née Interface Builder. Further, I would like to use Xcode's new-ish Auto Layout tools. Basically, these tools allow you to define inter-object constraints, and the runtime system figures out where said objects go.

Here's a simple example of what I want, in pseudo-code:

if (accelerometer == toTheLeft) {
    [topLevelView showSubview:leftView];
} else if (accelerometer == toTheRight) {
    [topLevelView showSubview:rightView];
} else {
    [topLevelView showSubview:centerView];
}

I know that to do the fictional showSubview: method, I'll actually have to remove whatever incorrect view is currently displayed, and add the one I want, but that's not the point here.

As mentioned before, I'd like to lay out each of these UIView objects (that is, leftView, rightView, and centerView) using Storyboard Editor/Interace Builder. When I go to do so, though, I end up with a confusing mess of different views stacked up on each other in IB. My view controller will ultimately add and remove the views from its view, but setting up the auto layout stuff is pretty hard this way.

Here's my question, finally. Is there a better way to have many, often overlapping views arranged straight-forwardly in the Storyboard editor for one view controller, or do I just have to set everything programmatically?


My introspective FAQ, for the avid reader:

  1. Why are you so set on Storyboard Editor/IB? It offers to automatically figure out a lot of the painful parts of view positioning and sizing. That sounds great! If I possibly can, I want to make it work for me.

  2. Someone must have asked this before, right? Uh, sorta. This question comes closest, out of those I found. However, this solution would still require me to set frames programmatically, negating what seems to me to be the best reason to use IB at all – auto-layout. This one got me excited, too, but isn't really about the same thing.

Community
  • 1
  • 1
ravron
  • 11,014
  • 2
  • 39
  • 66

2 Answers2

1

I had a similar situation in an application I was working on. What I did was that I added two container views to my main view controller (though you sound like you'll only need one). I deleted the embedded views within the containers, and added them as IBOutlets to my header file:

@property (weak, nonatomic) IBOutlet UIView *topContainerView;
@property (weak, nonatomic) IBOutlet UIView *bottomContainerView;

I then proceeded to create UIViewControllers for each of the three child views I wanted to use, which I could then design via the storyboard.

In my implementation file, I had two more properties,

@interface WorkOrderContainerViewController ()
@property UIViewController *topViewController;
@property UIViewController *bottomViewController;
@end

To switch between which of my view controllers was displayed, I used the following methods (I also had two similar methods for the bottom container view):

- (void)presentTopViewController:(UIViewController *)viewController
{
    // Remove current top view controller.
    if (topViewController != nil) {
        [self removeTopViewController];
    }

    [self addChildViewController:viewController];
    [[viewController view] setFrame:[topContainerView bounds]];
    [topContainerView addSubview:[viewController view]];
    [self setTopViewController:viewController];
    [viewController didMoveToParentViewController:self];
}

- (void)removeTopViewController
{
    [topViewController willMoveToParentViewController:nil];
    [[topViewController view] removeFromSuperview];
    [topViewController removeFromParentViewController];
}

I could then simply instantiate my views with

[self presentTopViewController:[storyboard instantiateViewControllerWithIdentifier:@"leftView"]];

I know you were looking for a way to manage overlapping views, but it'd probably be easier just to have each as a separate view controller and do it this way.

Kamaros
  • 4,536
  • 1
  • 24
  • 39
0

You could use a tab view controller, with three tabs, and then hide the tab bar. I think this would map quite well both technically and semantically to your scenario.

Danyal Aytekin
  • 4,106
  • 3
  • 36
  • 44