Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A protocol for view controllers with a replaceable content view controller
import UIKit
/// For a view controller that has no content of its own, implement like so:
///
/// extension RootViewController: ContentViewEmbedding {
/// var contentView: UIView! {
/// return view
/// }
/// }
protocol ContentViewEmbedding {
var contentView: UIView! { get }
}
extension ContentViewEmbedding where Self: UIViewController {
func removeContentViewController() {
guard let vc = childViewControllers.first(where: { $0.view.isDescendant(of: contentView) }) else { return }
vc.willMove(toParentViewController: nil)
vc.view.removeFromSuperview()
vc.removeFromParentViewController()
}
func replaceContentViewController(with vc: UIViewController, animated: Bool) {
let duration = animated ? 0.2 : 0
if let currentChild = childViewControllers.first {
currentChild.willMove(toParentViewController: nil)
addChildViewController(vc)
contentView.embedSubview(vc.view)
UIView.transition(
with: contentView,
duration: duration,
options: [.transitionCrossDissolve],
animations: setNeedsStatusBarAppearanceUpdate,
completion: { _ in
currentChild.view.removeFromSuperview()
currentChild.removeFromParentViewController()
vc.didMove(toParentViewController: self)
}
)
} else {
addChildViewController(vc)
contentView.embedSubview(vc.view)
vc.didMove(toParentViewController: self)
}
}
}
extension UIViewController {
@available(*, unavailable, message: "Please conform to 'ContentViewEmbedding'.")
func removeContentViewController() {}
@available(*, unavailable, message: "Please conform to 'ContentViewEmbedding'.")
func replaceContentViewController(with _: UIViewController, animated _: Bool) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.