I have a tableViewController in a containerView of another viewController.
When an image is tapped, a custom transition occurs to another viewController to view the image. The transition works well.
When the custom transition takes place though viewWillDisappear is called on the containerView's tableViewController and then viewWillAppear again when the presented viewController is dismissed (again with a transition).
This is causing some unusual scrolling occasionally in the tableView.
What I would like is to present the imageViewer with a transition but overCurrentContext.
I have tried what people suggest which is the following:
self.definesPresentationContext = true
vc.modalPresentationStyle = .overCurrentContext
vc.transitioningDelegate = self
self.present(vc, animated: true, completion: nil)
Unfortunately this is not working and when the imageViewController is dismissed, initially the transition back is correct and the tableViewController can be seen. But once the transition is complete the view goes black.
I think this may have to do with the fact that I'm using a containerView. But not sure and not sure how to resolve this.
This is the animator method I'm using:
private var image: UIImage?
private var fromDelegate: ImageTransitionProtocol?
private var toDelegate: ImageTransitionProtocol?
// MARK: Setup Methods
func setupImageTransition(image: UIImage, fromDelegate: ImageTransitionProtocol, toDelegate: ImageTransitionProtocol) {
self.image = image
self.fromDelegate = fromDelegate
self.toDelegate = toDelegate
}
// MARK: UIViewControllerAnimatedTransitioning
// 1: Set animation speed
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.4
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
// 2: Get view controllers involved
let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
// 3: Set the destination view controllers frame
toVC.view.frame = fromVC.view.frame
// 4: Create transition image view
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.frame = (fromDelegate == nil) ? CGRect() : fromDelegate!.imageWindowFrame()
imageView.clipsToBounds = true
containerView.addSubview(imageView)
// 5: Create from screen snapshot
fromDelegate!.transitionSetup()
toDelegate!.transitionSetup()
let fromSnapshot = fromVC.view.snapshotView(afterScreenUpdates: true)!
fromSnapshot.frame = fromVC.view.frame
containerView.addSubview(fromSnapshot)
// 6: Create to screen snapshot
let toSnapshot = toVC.view.snapshotView(afterScreenUpdates: true)!
toSnapshot.frame = fromVC.view.frame
containerView.addSubview(toSnapshot)
toSnapshot.alpha = 0
// 7: Bring the image view to the front and get the final frame
containerView.bringSubview(toFront: imageView)
let toFrame = (self.toDelegate == nil) ? CGRect() : self.toDelegate!.imageWindowFrame()
// 8: Animate change
UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: .curveEaseOut, animations: {
toSnapshot.alpha = 1
imageView.frame = toFrame
}, completion:{ [weak self] (finished) in
self?.toDelegate!.transitionCleanup()
self?.fromDelegate!.transitionCleanup()
// 9: Remove transition views
imageView.removeFromSuperview()
fromSnapshot.removeFromSuperview()
toSnapshot.removeFromSuperview()
// 10: Complete transition
if !transitionContext.transitionWasCancelled {
containerView.addSubview(toVC.view)
}
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
And this is in the presenting viewController:
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let imagePresentationViewController = (presented as! UINavigationController).topViewController as! ImagePresentationViewController
self.transition.setupImageTransition( image: pickedImageForTransition!, imageType: nil,
fromDelegate: self,
toDelegate: imagePresentationViewController)
return transition
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let imagePresentationViewController = (dismissed as! UINavigationController).topViewController as! ImagePresentationViewController
transition.setupImageTransition( image: pickedImageForTransition!, imageType: .listsImage,
fromDelegate: imagePresentationViewController,
toDelegate: self)
return transition
}