Mike Vosseller Mike Vosseller - 1 month ago 22
iOS Question

How to use Auto Layout with container transitions?

How can you use Auto Layout with the UIViewController container transition method:

-(void)transitionFromViewController:(UIViewController *)fromViewController
toViewController:(UIViewController *)toViewController
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion;

Traditionally, using Springs/Struts, you set the initial frames (just before calling this method) and set up the final frames in the animation block you pass to the method.

That method does the work of adding the view to the view hierarchy and running the animations for you.

The problem is that you we can't add initial constraints in the same spot (before the method call) because the view has not yet been added to the view hierarchy.

Any ideas how I can use this method along with Auto Layout?

Below is an example (Thank you cocoanetics) of doing this using Springs/Struts (frames)

- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController

// XXX We can't add constraints here because the view is not yet in the view hierarchy
// animation setup
toViewController.view.frame = _containerView.bounds;
toViewController.view.autoresizingMask = _containerView.autoresizingMask;

// notify
[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];

// transition
[self transitionFromViewController:fromViewController
completion:^(BOOL finished) {
[toViewController didMoveToParentViewController:self];
[fromViewController removeFromParentViewController];


Starting to think the utility method transitionFromViewController:toViewController:duration:options:animations:completion can not be made to work cleanly with Auto Layout.

For now I've replaced my use of this method with calls to each of the "lower level" containment methods directly. It is a bit more code but seems to give greater control.

It looks like this:

- (void) performTransitionFromViewController:(UIViewController*)fromVc toViewController:(UIViewController*)toVc {

    [fromVc willMoveToParentViewController:nil];
    [self addChildViewController:toVc];

    UIView *toView = toVc.view;
    UIView *fromView = fromVc.view;

    [self.containerView addSubview:toView];

    // TODO: set initial layout constraints here

    [self.containerView layoutIfNeeded];

    [UIView animateWithDuration:.25

                         // TODO: set final layout constraints here

                         [self.containerView layoutIfNeeded];

                     } completion:^(BOOL finished) {
                         [toVc didMoveToParentViewController:self];
                         [fromView removeFromSuperview];
                         [fromVc removeFromParentViewController];