Short version:
I am having a problem with auto layout top layout guide when used in conjunction with custom transition and UINavigationController
in iO
I ran into this same issue but without using a UINavigationController
and just positioning a view off of the topLayoutGuide
. The layout would be correct when first displayed, a transition would take place to another view, and then upon exiting and returning to the first view, the layout would be broken as that topLayoutGuide
would no longer be there.
I solved this problem by capturing the safe area insets prior to the transition and then reimplementing them, not by adjusting my constraints, but by setting them on the viewController's additionalSafeAreaInsets
.
I found this solution to work well as I don't have to adjust any of my layout code and search through constraints and I can just reimplementing the space that was there previously. This could be more difficult if you are actually using the additionalSafeAreaInsets
property.
I added a variable to my transitionManager to capture the safe insets that exist when the transitionManager is created.
class MyTransitionManager: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
private var presenting = true
private var container:UIView?
private var safeInsets:UIEdgeInsets?
...
Then during the entering transition I save those insets.
let toView = viewControllers.to.view
let fromView = viewControllers.from.view
if #available(iOS 11.0, *) {
safeInsets = toView.safeAreaInsets
}
In the case of the iPhone X this looks something like UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
Now when exiting, the insets on that same view we transitioned from in the entrance will be .zero
so we add our captured insets to the additionalSafeAreaInsets
on the viewController, which will set them on our view for us as well as update the layout. Once our animation is done, we reset the additionalSafeAreaInsets
back to .zero
.
if #available(iOS 11.0, *) {
if safeInsets != nil {
viewControllers.to.additionalSafeAreaInsets = safeInsets!
}
}
...then in the animation completion block
if #available(iOS 11.0, *) {
if self.safeInsets != nil {
viewControllers.to.additionalSafeAreaInsets = .zero
}
}
transitionContext.completeTransition(true)