Created
February 6, 2019 16:32
-
-
Save sharplet/26cd42811792d0f90f49487f381f837d to your computer and use it in GitHub Desktop.
A protocol for view controllers with a replaceable content view controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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