I have the following 2 functions that add and remove child view controllers triggered from a container view controller:
@discardableResult func addChildViewController(withChildViewController childViewController: UIViewController) -> UIViewController {
// Add Child View Controller
addChildViewController(childViewController)
childViewController.beginAppearanceTransition(true, animated: true)
// Add Child View as Subview
view.addSubview(childViewController.view)
// Configure Child View
childViewController.view.frame = view.bounds
childViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Notify Child View Controller
childViewController.didMove(toParentViewController: self)
return childViewController
}
@discardableResult func removeChildViewController(withChildViewController childViewController: UIViewController) -> UIViewController {
// Notify Child View Controller
childViewController.willMove(toParentViewController: nil)
childViewController.beginAppearanceTransition(false, animated: true)
// Remove Child View From Superview
childViewController.view.removeFromSuperview()
// Notify Child View Controller
childViewController.removeFromParentViewController()
return childViewController
}
The functions above are extensions to UIViewController, so all I'm doing is self.addChildViewController() and self.removeChildViewController() on the parent view controller.
How do I animate the view being removed on its way out and the view being added on its way in?
Animating between different child view controllers:-
func cycleFromViewController(oldViewController: UIViewController, toViewController newViewController: UIViewController) {
oldViewController.willMove(toParentViewController: nil)
newViewController.view.translatesAutoresizingMaskIntoConstraints = false
self.addChildViewController(newViewController)
self.addSubview(subView: newViewController.view, toView:self.containerView!)
newViewController.view.alpha = 0
newViewController.view.layoutIfNeeded()
UIView.animate(withDuration: 0.5, delay: 0.1, options: .transitionFlipFromLeft, animations: {
newViewController.view.alpha = 1
oldViewController.view.alpha = 0
}) { (finished) in
oldViewController.view.removeFromSuperview()
oldViewController.removeFromParentViewController()
newViewController.didMove(toParentViewController: self)
}
}
In above,
- oldViewController:- Current displayed child viewController
- newViewController:- New child view controller that will going to add
- containerView:- A view in which all child controllers are displaying.
To animate child view, you can use different type of animation style by replacing transitionFlipFromLeft to available UIViewAnimationOptions according requirement.
Answer of Sagar is not complete addSubview
method is missing there
Here is full answer
func cycleFromViewController(oldViewController: UIViewController, toViewController newViewController: UIViewController) {
oldViewController.willMove(toParentViewController: nil)
newViewController.view.translatesAutoresizingMaskIntoConstraints = false
self.addChildViewController(newViewController)
self.addSubview(subView: newViewController.view, toView:self.containerView!)
newViewController.view.alpha = 0
newViewController.view.layoutIfNeeded()
UIView.animate(withDuration: 0.5, delay: 0.1, options: .transitionFlipFromLeft, animations: {
newViewController.view.alpha = 1
oldViewController.view.alpha = 0
}) { (finished) in
oldViewController.view.removeFromSuperview()
oldViewController.removeFromParentViewController()
newViewController.didMove(toParentViewController: self)
}
}
//--------------------------------------------------------------------------------
private func addSubview(subView:UIView, toView parentView:UIView) {
self.view.layoutIfNeeded()
parentView.addSubview(subView)
subView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor).isActive = true
subView.topAnchor.constraint(equalTo: parentView.topAnchor).isActive = true
subView.bottomAnchor.constraint(equalTo: parentView.bottomAnchor).isActive = true
subView.trailingAnchor.constraint(equalTo: parentView.trailingAnchor).isActive = true
}
Hope it is helpful to someone