8
votes

I have a custom push transition between view controllers embedded in a UINavigationController which is working fine when built with iOS 7/8 but presents a wrong layout when built against iOS 9 SDK.

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
  UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

  [transitionContext.containerView addSubview:toViewController.view];

  ...

It then goes on and performs an animation. The issue is that the content of the toViewController, even though it is using the right top layout guide auto layout constraint, presents the content behind the navigation bar.

Nevertheless, it works fine on iOS 8 and if we force a redraw (e.g., sending the app to the background and bring it back, present a modal on top and dismiss it, etc) will cause the whole auto layout system to redraw itself and toViewController's view jumps to the right place (as being the top layout guide, x pixels from the navigation bar rather than x pixels from the top of the device's screen).

Adding

[self.view setNeedsUpdateConstraints];
[self.view layoutIfNeeded];

Works if put in viewDidAppear:animated, but does not work on viewDidLoad or viewWillAppear:animated. This is not a solution as users would see the view jumping when the redraw is happening at viewDidAppear:animated

1

1 Answers

24
votes

I've managed to fix my issue by adding the following line before addSubview::

  toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];

From Apple's Documentation for finalFrameForViewController:

Returns the ending frame rectangle for the specified view controller’s view.

The rectangle returned by this method represents the size of the corresponding view at the end of the transition. For the view being covered during the presentation, the value returned by this method might be CGRectZero but it might also be a valid frame rectangle.