Search code examples
iosswiftuicontainerviewuinavigationcontroller

How can I elegantly navigate from one embedded view to another (with layout in IB)?


In this app the user can do either Activity A or B. When doing A, the viewer sees embedded View A; but also during A the viewer can choose to see embedded View B. (The same goes for Activity B, only with converse views.)

My setup in IB is diagrammed below. Not knowing any better way, I created twice as many activity scenes as I would have liked: For the "Do Activity A" branch, I have two side-by-side copies of the Activity A scene. The first one has an embed segue to View A; and the second, an embed segue to View B. (The "B" setup is the converse.)

To avoid more duplication, I did make both activity branches share Views A and B. And although the activity scenes were doubled, the classes that they link to (ActivityAViewController and ActivityBViewController) were not. I haven't yet noticed any complications from that. . . .

In contrast to other workarounds I've seen, I chose the above "push–pop" layout because Views A and B are expensive. I don't want to discard the primary view just to load the secondary, and I don't want to load both unnecessarily. Also, I want to do this in IB because the real app is more complicated, and seeing all of my layout there helps me understand and develop it. With that said, my approach still seems klutzy.

My questions are

  1. Is there a better way to set this up in IB?
  2. What happens with the activity scenes' shared view controllers? Is a separate class instance created for each, or do the two scenes end up sharing the same instance?
  3. Similarly, what happens with the shared views?

Apple's explanations seem clear enough, though they assume more knowledge of Cocoa Touch and related jargon than I currently have. Any clarifications and insights will be appreciated.

Storyboard of Navigation With Embedded Views


Solution

  • Is there a better way to set this up in IB?

    There are other ways to set it up. They all have tradeoffs. Your method has a certain look, and if you want to hook it up differently, it will look a little different. Your method also has the advantage that all of the navigation is handled by the Storyboard; no extra code is needed.

    Alternatives include imbedding views A and B in their own little navigation controller. Then switching to view the other would involve clicking on that navigationController. This avoids the duplication of the outer Activity A and B controllers, but it would change the look by adding a navigationBar to the embedded views.

    You could also do that and hide the navigation bar and pass a message from the outer Activity A or B controller to tell it when to push the other viewController. This has the disadvantage of some additional nontrivial coding; the Storyboard no longer manages the navigation for you.

    You could also run this in a UITabBarController. That has the disadvantage of creating both Activity A and Activity B at the same time if you only need one, but you can freely switch between them without any recreation of any of the views.

    What happens with the activity scenes' shared view controllers? Is a separate class instance created for each, or do the two scenes end up sharing the same instance?

    Every segue (including embedded segues) creates a new viewController instance. No instances are shared.

    Similarly, what happens with the shared views?

    A new instance of A and B will be created each time.