How to Pass Data to an iOS Container View

After writing my previous post on adding an iOS container view, I received a couple of questions about how to pass data to the container view. This is a great question because the answer is not obvious to a person just learning iOS. In this post, I will show you how to keep a reference to your container view’s view controller to pass data or call functions on it.

Segues for Different Purposes

When you think of segues, you may think they are only for transitioning from one scene in your storyboard to another. In this diagram, we are using show segues to transition from one top-level view controller (scene) to another.
What we learned in my previous post was that segues can also be used to embed container views in your view controller.
AddContainerViewWe are going to take advantage of the fact that iOS treats all segues the same in order to solve our problem.

Prepare for That Segue

One of the functions you can override in your view controller is prepareForSegue. It is commonly used to pass data from one view controller to another for a show segue.

In that case, it is called just before you make the transition from one scene to another. In the moment before the transition, both view controllers exist in memory. The prepareForSegue allows you to get a reference to the destination of the transition and pass any data along to the next view controller.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "TransitionToSecondViewController") {
        let secondViewController = segue.destinationViewController  as! SecondViewController
        // Pass data to secondViewController before the transition

But what about embed segues and container views? Though it may not be obvious to people learning iOS, this function is also called to prepare for the embed segue that happens when a parent view controller contains a container view. In this situation, the destination view controller is the child view controller of your container view.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
    if (segue.identifier == "myEmbeddedSegue") {
        let childViewController = segue.destinationViewController as! myChildViewController
        // Now you have a pointer to the child view controller. 
        // You can save the reference to it, or pass data to it.

After prepareForSegue has been called, you can optionally store the reference to the child view controller in a property on your view controller. We can be assured that the lifecycle of the child view controller will remain as long as the parent view controller is alive.

Name That Segue

You can tell from my code samples above that I am checking to see if the segue matches an identifier. Because prepareForSegue can be called for different types of segues, we need to make sure we are operating on the segue we are interested in.

To identify a segue, in interface builder, click on a segue and give it a storyboard identifier in the attribute inspector.

Timing of prepareForSegue

My last piece of advice is to keep in mind that the view for the destination view controller is not loaded when prepareForSegue is called. This is true for all types of segues. The viewDidLoad function has not been called yet for your child view controller. Therefore, you cannot directly manipulate UI elements on the destination view controller inside the prepareForSegue function. It is better to set some state property on the child view controller and let it configure itself properly when its own viewDidLoad is called.

Catch up on my other posts in this series:

For more on using Xcode, read my series on unwind segues: