How To Use Container View In Swift 4

Posted By : Gunjan Gumber | 29-Apr-2018
Apple has provided us many view controllers like TableView controller, TabBar controller,Navigation View Controller. And for most the projects we use these standard View Controllers.But for some the projects, with unique design, according to the requirement we can use Container View Controller.
 
We can create a reusable component using container View and also this reusable component can be shared among all of view controllers.
 
Introduction of container Views has made reusability very easy as before the introduction of container views, we had to create reusable view using UIViews and then we had to programatically add them while loading , which was very time consuming task.
 
Steps to set up container View:-
 
Step 1: First of all , from the object library search for container view and then drag and drop the container view in your view controller(Let's name it as MainViewContsroller.Swift) in the Storyboard.
Step 2: After that tap on the container View and apply constraints to the it.
Step 3: Now create a custom class for container View. Click on File -> New -> File and create a CocoaTouch class and add the following code in that class.
import UIKit
    
    class ContainerViewController: UIViewController {
        
        //Manipulating container views
        fileprivate weak var viewController : UIViewController!
        //Keeping track of containerViews
        fileprivate var containerViewObjects = Dictionary()
        /** 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
                    
                }
                addDictionary(segue:segue)
                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)
                })
            }
        }
        
        func addDictionary(segue: UIStoryboardSegue) {
            //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
                    }
                }
            }
        }
}
Step 4: Now click on the view controller of container View in the storyboard and choose identity inspector from the top right and type your class name in the class field and press enter.
Step 5: Now for swapping between two controllers I have taken UISegmented ViewController in the MainViewContsroller.Swift file(We can can anything to swap as per requirement) and also create an outlet for the UISegmented control
@IBOutlet var segmentedControl: UISegmentedControl!

Step 6 : Now add two other view controller from object library in the storyboard and from the identity inspector set the class of both the view controllers.

Step 7 : Now from the container View create a custom segue to both the class and initailze seprate identifier for both of them from identity inspector.

Step 8: In your main View Controller, add the following code:-

 

import UIKit
    
 class MainViewController: UIViewController {
        
 var container: ContainerViewController!

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            if segue.identifier == "ContainerView"{
                container = segue.destination as! ContainerViewController
                container.animationDurationWithOptions = (0.5, .transitionCrossDissolve)
            }
        }
  @IBAction func segmentControl(_ sender: UISegmentedControl) {
        if sender.selectedSegmentIndex == 0{
            
            
            container!.segueIdentifierReceivedFromParent("first")
        }else{
            container!.segueIdentifierReceivedFromParent("second")
               }   
    }

In the line 8 , "ContainerView" is the identifier which we have to set for the custom segue for ContainerViewController

In the line 17 , "first" is the identifier which we have to set for the custom segue for FirstViewController.

In the line 19 , "second" is the identifier which we have to set for the custom segue for SecondViewController.

Thanks

About Author

Author Image
Gunjan Gumber

Gunjan is a bright IOS developer with good knowledge in Swift ,Json, quite good at building user interface.

Request for Proposal

Name is required

Comment is required

Sending message..