2
votes

StoryBoard setup

I have a project with StoryBoard (iOS 5+), with two UIViewController.

The task would be to instantiate programmatically a second UIViewController (CoordinationController) but I'd like to use it's XIB file for the user interface design.

The evident workaround to copy the XIB to StoryBoard is not working or not usable for undocumented reasons. Even the rule would be that in case the view controller of the second storyboard has no view it will look for the same named XIB... is not working.

How to instantiate the second UIViewController and use its XIB file?

2

2 Answers

5
votes

You can load the nib file and set your view in an initWithCoder: method of CoordinationController:

-(id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        UINib *nib = [UINib nibWithNibName:@"CoordinationController" bundle:nil];
        NSArray *nibObjects = [nib instantiateWithOwner:self options:nil];
        self.view = nibObjects.lastObject;
    }
    return self;
}
5
votes

A very simple solution is to override the view controller's nibName property and return the name of the nib that encodes the view you want loaded:

- (NSString*) nibName
{
    NSLog( @"p.s. this is the nib that the storyboard generated: %@", [super nibName]);

    return @"MyViewController";
}

Note that you can access the name of the nib generated by the storyboard compiler, which would have been used. This nib is included in the app bundle, packaged inside the storyboard.storyboardc bundle.

I am somewhat surprised that you cannot return nil from this nibName implementation and get the default behavior where the loader searches for a nib using the rules described in the docs.

Alternatively (and this is cheating) you could set the desired nib name in the Storyboard itself for the view controller via a user-defined runtime attribute with key nibName. This works because there is an undocumented setter for the property, so don't actually do this!

I think this is a better solution than the accepted answer because the view will be loaded in the normal course of the view-controller's lifecycle - that is, it will be lazily loaded before the controller is presented vs up front in the init method. And it is less code.