Exploring The Container View
I just finished building an app where the user signs in using a personal email and password, I wanted the app to open directly to the main feed if the user has already signed in and hasn’t signed out. To achieve this, I used a view controller that will be responsible for controlling which view will be the first, and I called this “App Controller”.
To give the App Controller this ability, we need to do some steps, so lets start building this amazing view controller. First, we need to add container view to the view of the App Controller.
Container View defines a region within a view controller’s view subgraph that can include a child view controller.
That means, we are creating a parent-child container relationship, where the parent is our App Controller and the container view object is a placeholder object that represents the contents of a child view controller. Before adding any child we have to manage the size and position of the container view because it will be reflected on the child properties. In my app I constrained the container view to the edges of the App Controller’s view, so any child will be displayed by the whole screen.
Second, I used the Notification Center to control the switching from one child to another, so I added notification observers to the App Controller where the selector for each observer is a function that will implement the switching. The code of add notification observers will be:
And the code for the selector will be:
I created an Enum for the storyboard ID to help me when I want to instantiate a view controller using its identifier from the storyboard. I also created an extension for the notification name to make it easier to use and avoid mistakes in writing the name.
The first part of the code has two functions. The first one is self-explanatory, switch view controller using the name of the notification, here I have two cases, either closing the login VC and opening the main VC or vise versa. To perform this switching I am calling another function in each case to do the closing and opening process using the storyboard ID. This function is the private function in the snippet “switchToViewController(with id: StoryboardID)”. As per the documentation form Apple, the transition cycle from old VC to new VC has two steps, adding a child View Controller to your content, and removing a child View Controller.
The first thing we need to do in this transition cycle is to prepare the two view controllers for the change, by calling the old child’s
willMoveToParentViewController: method with the value
Called just before the view controller is added or removed from a container view controller.
Your view controller can override this method when it needs to know that it has been added to a container.
If you are implementing your own container view controller, it must call the
willMoveToParentViewController:method of the child view controller before calling the
removeFromParentViewControllermethod, passing in a parent value of
When your custom container calls the
addChildViewController:method, it automatically calls the
willMoveToParentViewController:method of the view controller to be added as a child before adding it.
Now, let’s start the adding child step. To make the code cleaner, I created two separate functions, loadViewController(withID: ) to instantiate the view controller by using the storyboard ID, and add(viewController: ) that will implement the adding process following the Apple documentation as it is shown in the next snippet.
Let’s go line by line in the second function to see how we added child to our container view. In the first line we called the method addChildViewController , and this method is responsible for creating the parent-child relationship. Then add the view of the new VC to the container view and specify the size and the position. Finally, call didMoveToParentViewController: and the parent in this case will be the App Controller.
To implement the removing process, we need to remove the child’s root view from our container’s view by calling view.removeFromSuperview(), then call the child’s
removeFromParentViewController method to finalize the end of the parent-child relationship. Finally the last step, call the new child’s didMoveToParentViewController:, where the parent VC is the App Controller
After doing all these steps, I created a function that will handle the logic that manages which VC should be displayed when the user opens the app. In my case, since I am using the Firebase Auth, I will check if the current user is not nil, then I will display the main VC, otherwise I will display the login VC. I called this function in addition to addNotificationObservers function inside the viewDidLoad() of my App Controller.
Inside my login VC when the user clicks on the sign in button, a notification will be posted to close the login VC, and inside the main VC when the user clicks on log out button a notification to close the main VC will be posted. In both cases the App controller will be listening to these notification.
This was only a simple example for using the container view, it can be used for Segment Control, Navigation Controller, or Tab Controller.
Thanks to my amazing instructors Jim and Joel, and Apple documentation.