Categories: Swift Programming

Container View in iOS

Hello everyone!
I hope everyone would be doing great.

I googled for a long time but I couldn’t find any good tutorial for Container View, I read a tutorial where two Container Views were stacked over one another to achieve the required task, which is certainly not the proper way to do it.

Anyway, I am going to do a tutorial on Container View. So, Lets get started without wasting any further time.

Create a new project and drag a Container View along with two Buttons over a View Controller.

Drag a View Controller and connect Container View Controller with an Empty Segue to it. After that select the newly added View Controller open the Size Inspector and set the Simulated Size to Freeform and adjust the width and height of the controller according to the Container View Controller.

Resulting (in my case):

Repeat the same step for a second View Controller.

Your Storyboard will more or less look like this:

After that, add three classes of type UIViewController, i.e two for child view controllers(Let’s say FirstViewController.swift and SecondViewController.swift) and one for container view controller(ContainerViewController.swift), also add a class of type UIStoryboardSegue. Add all these classes to View Controllers and Empty Segues on storyboard, respectively.
When done adding classes, give identifiers to Embedded and Empty segues.

Open up your ViewController.swift class, create two action functions of the buttons that you added in the start, and paste the following code inside:

class ViewController: UIViewController {
    
    
    
    var container: ContainerViewController!

    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @IBAction func segmentControl(_ sender: UISegmentedControl) {
        
        
        if sender.selectedSegmentIndex == 0{
            container!.segueIdentifierReceivedFromParent("first")
            
        }else{
            container!.segueIdentifierReceivedFromParent("second")
        }
        
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "container"{
            container = segue.destination as! ContainerViewController
            //For adding animation to the transition of containerviews you can use container's object property
            // animationDurationWithOptions and pass in the time duration and transition animation option as a tuple
            // Animations that can be used 
            // .transitionFlipFromLeft, .transitionFlipFromRight, .transitionCurlUp
            // .transitionCurlDown, .transitionCrossDissolve, .transitionFlipFromTop
            container.animationDurationWithOptions = (0.2, .transitionFlipFromBottom)
        }
    }
    
    
}

In your ContainerViewController.swift, paste the following code:

class ContainerViewController: UIViewController {
    //Manipulating container views
    fileprivate weak var viewController : UIViewController!
    //Keeping track of containerViews
    fileprivate var containerViewObjects = Dictionary<String,UIViewController>()
    // Pass in a tuple of required TimeInterval with UIViewAnimationOptions 
    var animationDurationWithOptions:(TimeInterval, UIViewAnimationOptions) = (0,[])
    
    // Specifies which ever container view is on the front 
    open var currentViewController : UIViewController{
        get {
            return self.viewController
            
        }
    }
    
    
    fileprivate var segueIdentifier : String!
    
    //Identifier For First Container SubView
    @IBInspectable internal var firstLinkedSubView : String!
    
    
    override open func viewDidLoad() {
        super.viewDidLoad()
        
    }
    open override func viewDidAppear(_ animated: Bool) {
        if let identifier = firstLinkedSubView{
            segueIdentifierReceivedFromParent(identifier)
        }
    }
    override open func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func segueIdentifierReceivedFromParent(_ identifier: String){
        
        self.segueIdentifier = identifier
        self.performSegue(withIdentifier: self.segueIdentifier, sender: nil)
        
    }
    
    
    
    
    override open func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == segueIdentifier{
            //Remove Container View
            if viewController != nil{
                viewController.view.removeFromSuperview()
                viewController = nil
                
            }
            //Add to dictionary if isn't already there
            if ((self.containerViewObjects[self.segueIdentifier] == nil)){
                viewController = segue.destination
                self.containerViewObjects[self.segueIdentifier] = viewController
                
            }else{
                for (key, value) in self.containerViewObjects{
                    
                    if key == self.segueIdentifier{
                        viewController = value
                    }
                }
                
            }
            UIView.transition(with: self.view, duration: animationDurationWithOptions.0, options: animationDurationWithOptions.1, animations: {
                self.addChildViewController(self.viewController)
                self.viewController.view.frame = CGRect(x: 0,y: 0, width: self.view.frame.width,height: self.view.frame.height)
                self.view.addSubview(self.viewController.view)
            }, completion: { (complete) in
                self.viewController.didMove(toParentViewController: self)
            })
           
           
            
        }
        
    }
    
    
}

And in your Empty Segue class:

class Empty: UIStoryboardSegue{

override func perform() {

}
}

After that you’re good to go.
Here is a video tutorial for this.

I have uploaded this project on Github for reference.
Cheers!

Aaqib Hussain

View Comments

Recent Posts

Things to know when moving to Germany

This article covers some important things you must know when you are considering a move…

3 years ago

Unit Testing in Android for Dummies

What is Unit Testing? In its simplest term, unit testing is testing a small piece…

4 years ago

Factory Design Pattern

In this article, you will learn about a type of Creational Design Pattern which is…

5 years ago

Creating Target specific Theme in iOS

In this tutorial, you will go through the use of targets to achieve two separate…

5 years ago

Facade Design Pattern

In this article, you will learn about a type of Structural Design Pattern which is…

5 years ago

Singleton Design Pattern

In this article you will learn about a type of Creational Design Pattern which is…

5 years ago