Gemini/Gemini-iOS/UIViewController+Children.swift

87 lines
3.0 KiB
Swift

//
// UIViewController+Children.swift
// Gemini-iOS
//
// Created by Shadowfacts on 12/17/20.
//
import UIKit
// Based on MVCTodo by Dave DeLong: https://github.com/davedelong/MVCTodo/blob/841649dd6aa31bacda3ad7ef9a9a836f66281e50/MVCTodo/Extensions/UIViewController.swift
extension UIViewController {
func embedChild(_ newChild: UIViewController, in container: UIView? = nil) {
// if the view controller is already a child of something else, remove it
if let oldParent = newChild.parent, oldParent != self {
newChild.beginAppearanceTransition(false, animated: false)
newChild.willMove(toParent: nil)
newChild.removeFromParent()
if newChild.viewIfLoaded?.superview != nil {
newChild.viewIfLoaded?.removeFromSuperview()
}
newChild.endAppearanceTransition()
}
// since .view returns an IUO, by default the type of this is "UIView?"
// explicitly type the variable because We Know Better
var targetContainer: UIView = container ?? self.view
if !targetContainer.isContainedWithin(view) {
targetContainer = view
}
// add the view controller as a child
if newChild.parent != self {
newChild.beginAppearanceTransition(true, animated: false)
addChild(newChild)
newChild.didMove(toParent: self)
targetContainer.embedSubview(newChild.view)
newChild.endAppearanceTransition()
} else {
// the view controller is already a child
// make sure it's in the right view
// we don't do the appearance transition stuff here,
// because the vc is already a child, so *presumably*
// that transition stuff has already appened
targetContainer.embedSubview(newChild.view)
}
}
func removeViewAndController() {
view.removeFromSuperview()
removeFromParent()
}
}
// Based on MVCTodo by Dave DeLong: https://github.com/davedelong/MVCTodo/blob/841649dd6aa31bacda3ad7ef9a9a836f66281e50/MVCTodo/Extensions/UIView.swift
extension UIView {
func embedSubview(_ subview: UIView) {
if subview.superview == self { return }
if subview.superview != nil {
subview.removeFromSuperview()
}
subview.frame = bounds
addSubview(subview)
NSLayoutConstraint.activate([
subview.leadingAnchor.constraint(equalTo: leadingAnchor),
subview.trailingAnchor.constraint(equalTo: trailingAnchor),
subview.topAnchor.constraint(equalTo: topAnchor),
subview.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
func isContainedWithin(_ other: UIView) -> Bool {
var current: UIView? = self
while let proposedView = current {
if proposedView == other { return true }
current = proposedView.superview
}
return false
}
}