Instantiating custom views from nib

Hi again everyone!

Subclassing UIView to create your own custom class is one of the most frequent tasks an iOS developer has to do.

And for me at least, every time that i created my own custom view, i was torn apart by what is the correct and more convenient way to design my view – from code or from interface builder. I always thought that there was no “right answer”, and that this decision depends on the scenario.
I was wrong. Using interface builder is better. Let’s see why.

Why using a nib is better?

  • What you see is what you get – We have the best visual designer in the mobile industry, why not use it? The ability to see what the view looks like, and be able to instantly alter its layout is priceless, and will save you or your designer a lot of time.
  • Reusability – It’s always better to separate the view and the controller as much as possible, that way if you want to use a different view, you just pass on a different nib file instead of messing around with styles
  • Better understanding of the view hierarchy – complicated view hierarchy can Kill performance. It’s especially important for tableView cells. If you have a lot of subview inside subviews your scrolling get really messed up. When working with code, it’s sometimes hard to get a instant understanding of what our view hierarchy looks like, and how it can hurt performance. By the way, a lot of people will recommend you to simply draw the cell as one flat view to improve performance. This is rarely the best solution, but I will discuss this in a later post.
  • Performance – I was always under the impression that working with code is faster that instantiating from a nib file. Lucky for me, Matt Gallagher wrote a very good article on Cocoa with love explaining why in most cases, loading from nib is as good as loading from code, and sometimes even better.
When you get down to it, the only real case in which you have to layout the view from code is if you have custom drawing in the drawRect method. And if that’s the case, nib won’t help you any way.

So, how do we instantiate from nib?

To instantiate from nib, we have to follow those steps:

  1. In interface builder, create a nib file
  2. Add a UIView as the root view, and change it’s class to be our custom view (identity inspector -> class)
  3. Make sure you connect all the outlets to the custom view and not to the file owner. This is very important because it will not throw any compilation errors or warnings, your outlets will simply be nil at run time.
  4. Use the loadNibNamed method to grab the views array from the nib, and pick the first one that matches the class of our custom view.
I found that the easiest way to perform step 4, is to add an extension to UIView that we can use where ever we want. The code simply traverse the nibEnumerator, until it finds a view of the required class:
@implementation UIView (AUIInitialization)

+(UIView *) viewWithNibName:(NSString *)nibName owner:(NSObject *)owner {

    NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:owner options:NULL];
    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    id customView = nil;
    NSObject* nibItem = nil;
    while ((nibItem = [nibEnumerator nextObject]) != nil) {
        if ([nibItem isKindOfClass:[self class]]) {
            customView = nibItem;
            break;
        }
    }
    return customView;
}

@end

And that’s it.
With this method we don’t have to change our current custom view, and we can also use this method to instantiate the view using different nibs if we like.
I started an extension kit project to where i will add useful extensions like this one. You can find it on my github page.

Hope you’ll find this useful, and as always – I’d love to get you feedback and comments.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: