0

I've tried following numerous examples and other questions on SO. The view controller is being added but it is placing the view container into the view and not the view container. Here is a shot of what I mean.

enter image description here

I have a tab bar on the primary view controller and a container view. When an item on the tab bar is tapped, it is supposed to grab the controller and load it into the container view. Here is the code for how I am doing it.

@IBOutlet weak var tabBar: UITabBar!
@IBOutlet weak var containerView: UIView!
var currentViewController: UIViewController!
var radarViewController: UIViewController!

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    let storyboard = self.storyboard
    let currentViewController = storyboard?.instantiateViewController(withIdentifier: "WeatherCurrentViewController") as! WeatherCurrentViewController
    self.currentViewController = UINavigationController(rootViewController: currentViewController)
    let radarViewController = storyboard?.instantiateViewController(withIdentifier: "WeatherRadarViewController") as! WeatherRadarViewController
    self.radarViewController = UINavigationController(rootViewController: radarViewController)
}
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    if item.tag == 1 {
        containerView.addSubview(currentViewController!.view)
        currentViewController.didMove(toParentViewController: self)
    }

    if item.tag == 2 {
        containerView.addSubview(radarViewController!.view)
        radarViewController.didMove(toParentViewController: self)
    }
}

This is Swift 3. I don't know what it is I am doing incorrectly. Any help is appreciated.

Update

Although I never got the switching of view to work programmatically after numerous changes/tries, I did find another way of using segues with multiple view containers (here. Not the ideal since it ties up more memory but it works.

Community
  • 1
  • 1
Micah Montoya
  • 757
  • 1
  • 8
  • 24

1 Answers1

0

The view controller is just a wrapper around the UIView. So in the end you will always have the controllers view that is added as a subview to the container view.

The point of this is you will still get all of the notification for the view controller such as rotation change, layouts...

I use a class which is an UIView subclass. It looks something like this:

import UIKit

class ContentControllerView: UIView {

    weak var parrentViewController: UIViewController?
    private(set) var currentController: UIViewController?

    func setViewController(controller: UIViewController) {
        guard let parrentViewController = parrentViewController else {
            print("ContentControllerView error: You need to set a parrentViewController to add a new view controller")
            return
        }

        if controller.view != currentController?.view {
            currentController?.willMove(toParentViewController: nil) // Notify the current controller it will move off the parent
            controller.willMove(toParentViewController: parrentViewController) // Notify the new controller it will move to the parent
            parrentViewController.addChildViewController(controller) // Add child controller
            currentController?.view.removeFromSuperview()
            currentController?.didMove(toParentViewController: nil) // Notify the current controller it did move off the parent

            controller.view.translatesAutoresizingMaskIntoConstraints = false // Disable this to add custom constraints
            self.addSubview(controller.view) // Add as subview
            // Assign new constraints
            self.addConstraint(NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: controller.view, attribute: .left, multiplier: 1.0, constant: 0.0))
            self.addConstraint(NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: controller.view, attribute: .right, multiplier: 1.0, constant: 0.0))
            self.addConstraint(NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: controller.view, attribute: .top, multiplier: 1.0, constant: 0.0))
            self.addConstraint(NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: controller.view, attribute: .bottom, multiplier: 1.0, constant: 0.0))

            self.layoutIfNeeded()

            currentController?.removeFromParentViewController() // remove the current controller from parrent
            controller.didMove(toParentViewController: parrentViewController) // Notify the new controller it did move to the parent

            currentController = controller
        }
    }

}

The view can be added in the storyboard but then in the code you need to assign the view controller:

self.contentControllerView.parrentViewController = self
self.contentControllerView.setViewController(controller: controller)
Matic Oblak
  • 16,318
  • 3
  • 24
  • 43
  • Thanks Matic for showing me how you do this. I'd really like to understand what is about the code I have that isn't making it work other than just copying and pasting what someone else has done. Any insight you can offer? – Micah Montoya Nov 16 '16 at 16:47
  • Try comparing the calls – Matic Oblak Nov 16 '16 at 16:48