Skip to content

Instantly share code, notes, and snippets.

@timriley
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timriley/11f6716217b49c4b45a2 to your computer and use it in GitHub Desktop.
Save timriley/11f6716217b49c4b45a2 to your computer and use it in GitHub Desktop.
Workaround for dismissViewControllerAnimated failing to animate a stack of modal view controllers
- (void)loginViewControllerDidClose:(DSLoginViewController *)loginViewController
{
// HACK
//
// Work around a bug(?) where the login VC's view disappears immediately
// (without animation) before our own view then animates away. We want
// only the login VC's view to animate, with all underlying views
// disappearing (invisibly) underneath at the same time. AFAICT, this is
// what _should_ happen:
//
// > If you present several view controllers in succession, thus building
// > a stack of presented view controllers, calling this method on a view
// > controller lower in the stack dismisses its immediate child view
// > controller and all view controllers above that child on the stack.
// > When this happens, only the top-most view is dismissed in an animated
// > fashion; any intermediate view controllers are simply removed from
// > the stack.
//
// However, this is not what actually happens. To make it look right, we
// basically fake out the same effect below, which only works here because
// we know exactly what kind of context we'll have when the login screen
// is dismissed.
// Get an image snapshot of the login VC (including its navigation bar)
UIGraphicsBeginImageContextWithOptions(self.presentedViewController.view.bounds.size, YES, 0);
[self.presentedViewController.view drawViewHierarchyInRect:self.presentedViewController.view.bounds afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Add it to our own view
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
// And hide our navigation bar, since the snapshot includes the login VC's own navigation bar
[self.navigationController setNavigationBarHidden:YES animated:NO];
// Then dismiss yourself
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
@timriley
Copy link
Author

There is a stack of 2 modally presented view controllers, on top of my main view controller:

main VC -> compose VC -> login VC

When the login VC gets a tap on a “cancel” button, it sends a loginViewControllerDidClose message back to its delegate, which is the compose VC.

At which point the compose VC was just calling [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; This is meant to animate the stack of presented VCs away nicely, with the top-most VC’s view the one being animated away.

However, what I get is the login VC’s view disappearing immediately, without any animation, followed by the compose VC's view animating away.

This switching around of views before the animation occurs is a horrible look. What I want to happen is the login VC's view animating away, with all other views being sorted out invisibly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment