lmirosevic
lmirosevic

Reputation: 16317

How do you hook up IBOutlets across scenes in the Interface Builder storyboard?

I have a custom UITableViewController with 2 properties:

@property (strong, nonatomic) IBOutlet VenueHeaderViewController *header;
@property (strong, nonatomic) IBOutlet VenueFooterViewController *footer;

The UIViews of my VenueHeaderViewController and VenueFooterViewController were designed in IB. Each of these controllers has IBOutlets to its subviews as set up in the storyboard. This is my storyboard:

My question is, how do I now connect my header and footer IBOutlets inside my UITableViewController to instances of my VenueHeaderViewController and VenueFooterViewController while retaining the layout and IBOutlets which I have set up in the storyboard?

Upvotes: 4

Views: 1524

Answers (1)

rickster
rickster

Reputation: 126167

You can't hook up IBOutlets across different scenes in a storyboard. Scenes are each entirely self-contained, and only connected via segues (or relationships in the case of special container view controllers like tab, navigation, split view and popover controllers). If you've done any IB work without storyboards, think of each scene (view controller) as being in its own nib (in fact, that's what storyboards do behind the scenes).

Beyond that, it's generally the case (on iPhone at least) that there's a one-to-one mapping between a view controller and a "screen" of UI -- you generally don't have different view controllers managing different parts of the screen, as appears to be the case with the header, table, and footer you have. (Thus, you'll pretty much never have an IBOutlet to any UIViewController subclass.)

So what can you do? Here's a few different approaches, from easier to harder:

UITableView header & footer

If you're meaning to assign those header & footer views to the UITableView's tableHeaderView and tableFooterView properties, you can do that in the storyboard in IB -- just drag a UIView of some sort from the library toward the top or the bottom of the table until you see a blue line above or below the prototype cell(s):

drag view to table footer

The table header & footer views might or might not be what you're after, though: they're part of the scrolling content of the table (that is, they appear above the first row and below the last, respectively, so they can be scrolled off the screen).

Views above & below

If your intended use of these views is as "header" and "footer" in that they always appear above or below the table regardless of where it's scrolled, then what you really need is to have the header, footer and the table view all be subviews of a root view.

For that, you'll need a regular UIViewController subclass rather than a UITableViewController subclass. You can put a UITableView in as a subview of that view controller's root view, and arrange whatever other views you want to be visible above/below it. (Just make sure to set the autoresizing sensibly if you plan to support rotation.) Here's an example:

table view as subview

(If you're wondering where the prototype cells are when you first drag out the table view, check the inspector -- you set the number of them in the upper right of that screenshot.)

Top level views

With regular nibs (not storyboards), you can set up views in IB which aren't the view controller's root view. Then you can still connect outlets to them, and programmatically insert them into the view hierarchy as needed.

You can sort of do this in a storyboard, too -- drag views to the black bar beneath the scene -- but due to a bug in the current version of Xcode, you can't see these views for editing. Oops.

Multiple view controllers, really

If none of the above suit your needs, you might still have a use for multiple view controllers -- say, if you wanted to switch out different different header views at various times, and save memory by dynamically instantiating these view hierarchies as needed. Cases like this are pretty rare, though... you should make sure you've exhausted other options first.

In effect, you're still using one of the previous two approaches, but the views you want are located in other scenes (again, it's like they're in other nibs). Here, the view controllers holding the other views don't even need to be custom subclasses of UIViewController, since they're just temporary containers for views you want to insert into a different view controller's view hierarchy.

In that case, the storyboard you have is what you want... it's just a matter of getting those view controllers appropriately loaded, which you can do thusly:

SpecialViewController *svc = [storyboard instantiateViewControllerWithIdentifier:@"SpecialViewController"];

Then, pull the view property from each view controller, insert it into your "main" view controller's view hierarchy, and dispose of the the view controller you pulled it from.

Upvotes: 5

Related Questions