Skip to content

Commit 42d0b25

Browse files
Fixes animation race condition caused by quick transitions. Saving setting _viewController ivar outside of the animation ensures the 'current' controller is always known, and the animation completion block compares controllers prior to erroneously removing the 'current' controller. Also improving animations in quick transitions by reversing the fade directionality. Fading-in the new view could leave all views nearly translucent during quick transitions, but fading-out the old view allows there to always be a new opaque view behind it.
1 parent 2b056a5 commit 42d0b25

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

GRKContainerViewController/GRKContainerViewController.m

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,18 @@ - (void)setViewController:(UIViewController *)viewController animated:(BOOL)anim
6868
//We will use a simple cross fade animation, as indicated
6969
NSTimeInterval duration = animated ? self.transitionAnimationDuration : 0.0f;
7070

71-
//Set the new view controller's view to be transparent
72-
viewController.view.alpha = 0.0f;
71+
// We're fading out views, so make sure they're not invisible when we start.
72+
self.viewController.view.alpha = 1.0f;
73+
viewController.view.alpha = 1.0f;
7374

7475
//Add the new view controller to the view and view controller hierarchies
7576
if (viewController)
7677
{
7778
[self addChildViewController:viewController];
79+
80+
// Add the new view below the current view, and then fade out the current view.
7881
[self.view addSubview:viewController.view];
82+
[self.view insertSubview:viewController.view belowSubview:self.viewController.view];
7983
[viewController didMoveToParentViewController:self];
8084

8185
//Setup constraints to keep the new view pinned to our size.
@@ -85,22 +89,25 @@ - (void)setViewController:(UIViewController *)viewController animated:(BOOL)anim
8589
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[containedView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(containedView)]];
8690
}
8791

92+
// Hold onto the old controller, and set the new one.
93+
UIViewController *oldViewController = self.viewController;
94+
_viewController = viewController;
95+
8896
[UIView animateWithDuration:duration animations:^{
89-
//Set the new view controller's view to be visible
90-
viewController.view.alpha = 1.0f;
97+
// Animate away the old controller view.
98+
oldViewController.view.alpha = 0.0f;
9199
} completion:^(BOOL finished) {
92-
//Remove the previous view controller from the view and view controller hierarchies
93-
[self.viewController willMoveToParentViewController:nil];
94-
[self.viewController.view removeFromSuperview];
95-
[self.viewController removeFromParentViewController];
96-
97-
//Keep our new view controller
98-
_viewController = viewController;
100+
// Quick transitions can leave us trying to remove the view that has just been added. Only remove it if its not the same controller.
101+
if (_viewController != oldViewController) {
102+
[oldViewController willMoveToParentViewController:nil];
103+
[oldViewController.view removeFromSuperview];
104+
[oldViewController removeFromParentViewController];
105+
}
99106

100107
if (completion)
101108
{
102109
//Call the completion block with the new view controller
103-
completion(self.viewController);
110+
completion(viewController);
104111
}
105112
}];
106113
}

0 commit comments

Comments
 (0)