Search

Real iPhone Crap 2: initWithNibName:bundle: is the designated initializer of UIViewController

Aaron Hillegass

3 min read

Aug 12, 2009

iOS

Real iPhone Crap 2: initWithNibName:bundle: is the designated initializer of UIViewController

Before I go into another shortcoming of UIKit, I’d like to make it plain that I genuinely like most of UIKit. In many ways it is much better than AppKit. I love UIControl, and I think that UITableViewCell being a subclass of UIView is a huge step forward. But, the weaknesses are the parts that demand difficult design decisions, so I’m delving upon them in this series.


Like UIViewController, NSDocument was designed to be subclassed. They both can also load a nib file. Let’s look at how NSDocument does it.

The designated initializer of NSDocument is init. How then, does the subclasser specify the nib file to load? He implements windowNibName:

- (NSString *)windowNibName
{
    return @"CrapDocumentNib";
}

What is cool about this?

  • The name of the nib file is in exactly one place – inside the controller class that will be using the nib file

  • The NSDocument subclass and its nib file become a module that can be easily reused in other applications

  • Classes that use the NSDocument subclass don’t need to know anything about the nib file or whether it uses a nib file at all

In short, this design means that we can reap all the benefits of object encapsulation.

The designers of UIViewController, on the other hand, decided to make the designated initializer:

 - (id)initWithNibName:(NSString *)n bundle:(NSBundle *)b;

(I suspect that this had something to do with making it possible to specify the nib file inside Interface Builder.)

If you make initWithNibName:bundle: the initializer for your UIViewController subclass, wherever you create an instance, you must specify which nib file goes with it:

CrapViewController *cvc;
cvc = [[CrapViewController alloc] initWithNibName:@"CrapViewNib" 
                                           bundle:nil];

This makes no sense: the name of the nib file should be in one place, and that place should be inside CrapViewController.m. I see most developers putting the name of the nib file in a dazzling array of places: in code wherever the view controller is created and in nib files where view controllers are created.

Stylish iPhone programmers, however, are changing the designated initializer of their UIViewController subclass to init:

- (id)init
{
    [super initWithNibName:@"CrapViewNib" bundle:nil];
    ... give ivars initial values...
    return self;
}

Now being a fastidious Objective-C programmer, you must also override the designed initializer of the superclass to call your designated initializer:

- (id)initWithNibName:(NSString *)n bundle:(NSBundle *)b
{
    return [self init];
}

Voila! The benefits of object encapsulation are restored to your application:

CrapViewController *cvc = [[CrapViewController alloc] init];

(Can I mention that I, personally, don’t instantiate view controllers in nib files. Many of my view controllers act as the owner of nib files, but I always create the view controller itself programmatically. I don’t have a great argument for this, but I do find it easier to understand the work of developers who follow this guideline.)

Before I close this, I’d like to you to imagine how much easier it would have been if the UIViewController had followed the design of NSDocument. When you opened up any UIViewController subclass you would immediately look for the viewNibName method:

- (NSString *)viewNibName
{
    return @"CrapViewNib";
}

Now you know which nib file goes with the view controller. If the method returns nil, you would know that the view controller doesn’t use a nib file. If the method didn’t exist at all, you would know that the nib file’s name was the same as the class name.

Instead of two init methods, there would be one init method if you needed to initialize some instance variables and none if you didn’t.

And life would be a little bit better.


If you missed the last installment, you might want to read Real iPhone Crap 1.

Zack Simon

Reviewer Big Nerd Ranch

Zack is an Experience Director on the Big Nerd Ranch design team and has worked on products for companies ranging from startups to Fortune 100s. Zack is passionate about customer experience strategy, helping designers grow in their career, and sharpening consulting and delivery practices.

Speak with a Nerd

Schedule a call today! Our team of Nerds are ready to help

Let's Talk

Related Posts

We are ready to discuss your needs.

Not applicable? Click here to schedule a call.

Stay in Touch WITH Big Nerd Ranch News