I have two view controllers: viewController1
and viewController2
. viewController1
contains a collection view with several cells.
They are connected by a modal segue. For navigation between them I create two animators for showing viewController2
(showAnimator
) and for dismissing it (dismissAnimator
).
In dismissAnimator
I animate both the fromView
(viewController2
's view) and toView
(viewController1
's view). Here are the two methods for doing that:
private func animateFromViewDisappearance(fromView: UIView?, withDuration duration: TimeInterval, usingTransitionContext transitionContext: UIViewControllerContextTransitioning?) {
guard let containerView = transitionContext?.containerView, let fromView = fromView else {return}
UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .curveEaseInOut, animations: {
fromView.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
fromView.alpha = 0.0
}, completion: {_ in
})
}
private func animateToViewAppearance(toView: UIView?, withDuration duration: TimeInterval, usingTransistionContext transitionContext: UIViewControllerContextTransitioning?) {
guard let containerView = transitionContext?.containerView, let toView = toView else {
return}
toView.frame = containerView.frame
toView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
toView.alpha = 0.0
containerView.addSubview(toView)
UIView.animate(withDuration: duration, delay: 0.3, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .curveEaseInOut, animations: {
toView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
toView.alpha = 1.0
}) { (success) in
if success {
transitionContext?.completeTransition(true)
}
}
}
These methods are called from animateTransition(using:)
.
The problem is that after the animation ends, in viewController1
cells of the collection view don't appear. I just get the view of the view controller and the collection view itself. I've checked and noticed that lifecycle methods of the view controller don't get called either, however, viewDidLayoutSubviews
does get called. Collection view data source methods don't get called, too, so that's why the cells don't appear.
I know I'm missing something quite simple but can't figure out what. I've also checked a few answers here, but none of them helped me.
If you know how to resolve this problem, I would appreciate your help.
After spending some time I finally found a solution. As it is said in Apple's docs, we can't directly call view controller's lifecycle methods (well, we can but it isn't recommended). To call viewController1
lifecycle methods I call beginAppearanceTransition(_:animated:)
method from animator:
toViewController?.beginAppearanceTransition(true, animated: true)
Now, this indeed calls the view controller's lifecycle methods, but the view layout becomes a completely mess (I think, that's because when initially transitioning from the viewController1
I change not only its location but also its scale).
So, finally I found a solution to that problem, too. To solve it, when transitioning from viewController1
, I animate not the view controller itself (its location and scale), but I use its snapshot (the following code is in the animator for transitioning from viewController1
to viewController2
):
let snapshot = UIApplication.shared.keyWindow?.snapshotView(afterScreenUpdates: false)
After having the snapshot, as soon as the transition starts I insert the snapshot into the containerView
on top of a viewController1
, and remove viewController1
from the superview. Now, I animate the snapshot, which mimics the viewController1
.
This works fine for me. Maybe it will work for someone else.