I'm trying to add a child view controller to a parent controller using an extension to UIViewController. This works when I don't use the extension by calling the following to add the child controller:
addChild(child)
child.view.frame = view.frame
view.addSubview(child.view)
child.didMove(toParent: self)
And the following to remove the child view controller:
child.willMove(toParent: nil)
child.view.removeFromSuperview()
child.removeFromParent()
The expected result is that when the button is tapped the child view controller is added, the spinner view controller loads, UIActivityIndicatorView spins for two seconds and then the child view controller is removed. This works as expected when the extension is not used. There are no error messages. When using the extension the spinner does not appear - nothing happens.
SpinnerViewController.swift (not associated with a view controller scene in Interface Builder):
import UIKit
class SpinnerViewController: UIViewController {
var spinner = UIActivityIndicatorView(style: .whiteLarge)
override func loadView() {
view = UIView()
view.backgroundColor = UIColor(white: 0, alpha: 0.7)
spinner.translatesAutoresizingMaskIntoConstraints = false
spinner.startAnimating()
view.addSubview(spinner)
spinner.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
spinner.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
Here is ViewController.swift which is associated with a view controller scene in Interface Builder:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func pressToSpinButtonTapped(_ sender: UIButton) {
createSpinnerView()
}
func createSpinnerView() {
let child = SpinnerViewController()
// add the spinner view controller
// addChild(child)
// child.view.frame = view.frame
// view.addSubview(child.view)
// child.didMove(toParent: self)
self.add(child)
// wait two seconds to simulate some work happening
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
// then remove the spinner view controller
// child.willMove(toParent: nil)
// child.view.removeFromSuperview()
// child.removeFromParent()
self.remove()
}
}
}
@nonobjc extension UIViewController {
func add(_ child: UIViewController, frame: CGRect? = nil) {
addChild(child)
if let frame = frame {
child.view.frame = frame
}
view.addSubview(child.view)
child.didMove(toParent: self)
}
func remove() {
guard parent != nil else { return }
willMove(toParent: nil)
view.removeFromSuperview()
removeFromParent()
}
}