So I built a custom presenting transition animation and everything seems to be working great except the view controller lifecycle methods are not being called on dismiss.
Before presenting the controller I use the UIModalPresentationCustom
style to keep the presenting VC in the view hierarchy, but once I dismiss the presented VC, viewWillAppear and viewDidAppear are not called on my presenting controller. Am I missing a step that I need to explicitly call to get those methods to fire? I know manually calling those methods is not the correct solution.
Here is my dismissing animation code. I'm basically animating a form overlay view to shrink to the size of a collection view cell on dismissal.
- (void)_animateDismissingTransitionWithContext:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UICollectionView *destinationCollectionView = toCollectionViewController.collectionView;
UICollectionViewCell *destinationCollectionViewCell = [self _destinationCellFromContext:transitionContext];
UIView *containerView = transitionContext.containerView;
// Calculate frames
CGRect startFrame = fromEventDetailViewController.detailContainerView.frame;
CGRect endFrame = [destinationCollectionView convertRect:destinationCollectionViewCell.frame toView:containerView];
// Add overlay
UIView *overlayView = [UIView new];
overlayView.backgroundColor = [UIColor overlayBackground];
overlayView.frame = containerView.bounds;
overlayView.alpha = 1.0f;
[containerView addSubview:overlayView];
// Add fake detail container view
UIView *fakeContainerView = [UIView new];
fakeContainerView.backgroundColor = fromEventDetailViewController.detailContainerView.backgroundColor;
fakeContainerView.frame = startFrame;
[containerView addSubview:fakeContainerView];
// Hide from view controller
fromEventDetailViewController.view.alpha = 0.0f;
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0f usingSpringWithDamping:0.75f initialSpringVelocity:0.2f options:UIViewAnimationOptionCurveEaseOut animations:^{
fakeContainerView.frame = endFrame;
fakeContainerView.backgroundColor = [UIColor eventCellBackground];
overlayView.alpha = 0.0f;
} completion:^(BOOL finished) {
[fromEventDetailViewController.view removeFromSuperview];
[overlayView removeFromSuperview];
[fakeContainerView removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}
Another solution could be using beginAppearanceTransition: and endAppearanceTransition:. According to documentation:
If you are implementing a custom container controller, use this method to tell the child that its views are about to appear or disappear. Do not invoke viewWillAppear:, viewWillDisappear:, viewDidAppear:, or viewDidDisappear: directly.
Here is how I used them:
- (void)animationEnded:(BOOL)transitionCompleted
{
if (!transitionCompleted)
{
_toViewController.view.transform = CGAffineTransformIdentity;
}
else
{
[_toViewController endAppearanceTransition];
}
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
[toViewController beginAppearanceTransition:YES animated:YES];
// ... other code
}
But I still consider strange that custom modal presentation not doing this.