views:

688

answers:

3

I was wondering if there is a difference between using .xib files for GUI design and doing this programmatically.

As it is a compiler I would assume that there is no relevant time lost.

Am I wrong?

+9  A: 

Very little. There are some exceptions. For example, if you use a xib to load the image that goes into a UITableViewCell, then that could be a problem since UITableViews with many cells are sensitive to loading times. However, for all intents and purposes, there should be no noticeable performance hit.

The information in the xib does have to be decoded at runtime and loaded into memory, which is not as fast as just creating UI elements programmatically and directly.

mahboudz
If you reuse cells like you are supposed too, there will only be as many cells created as will fit on screen so the overhead is not all that much (you can set the reuse identifier in IB).
Kendall Helmstetter Gelner
True, the use of a xib for UITableViewCell only impacts its creation, and only for the number of visible cells, not all cells (unless you are doing something wrong).
mahboudz
+5  A: 

Beware premature optimization, especially when it involves writing a great deal more code than you need to.

NSResponder
True, but when it comes to the iPhone and its limited resources, optimizations that I would normally consider to be crazy can make an actual difference. Wil Shipley has some interesting comments on this: http://www.vimeo.com/4421498
Brad Larson
+9  A: 

(Note: Tapping this out on my phone, so I apologize ahead of time for any weird formatting or grammar - if there are issues, I'll fix them when I'm back at my laptop.)

I've done some quick, dirty, and extremely informal tests to check this out for myself, and here's what I found (note that the app I built for the tests was just scratch and not necessarily representative of a "real" app):

  • Startup time was faster when when the initial screen was a nib

  • For all subsequent screens, performance increased when coding the UI by hand

It's odd at first, but when you think about it, maybe it isn't really all that strange.

The startup issue confuses me, but I assume it's because Apple, being Apple and being obsessed with startup times (in a good way, of course), just optimized the phone's unarchiver in such a way that loading from an archive (nib) can be faster than coding by hand.

That said, most people write apps that aren't going to be significantly affected by any differences. My (again: quick and dirty) tests showed that, from a cold start (you haven't run the app yet or in a while), the nib-based app consistently loaded its initial screen about twice as fast as the hand-coded version. While that sounds like a big deal, we're talking just a few milliseconds. That difference will be imperceptible to users. For a warm start (you've already opened and closed the app), the differences for startup time were much smaller.

For this reason, I like to use nibs for laying out the foundation of an app: any top-level navigation (tab controllers, nav controllers, etc.), and then code the rest of the UI by hand.

Plus, because the iPhone UI is so specific to, well, the iPhone (surprise!), coding UIs by hand isn't difficult the way it is when writing desktop apps. You use the same UI components over and over - once you've got that down, whipping up a UI in code is easy. You don't have eight-billion widgets to choose from as you would developing a Windows/OS X/whatever application. The iPhone's consistency makes it the easiest platform I've developed against in ages when it comes to hand coding UIs.

I've also found that NSCoding (which is what I use for persisting state across app runs) is much easier to work with when I've hand-coded a UI. I've run into problems where a nib-based screen wouldn't properly archive because of UIImage instances. UIImage (at least the last time I checked) doesn't conform to NSCoding, so the archive process dies (and a rather unpleasant death it is). I used UIImage as an example here, but anything the archiver tries to store that doesn't conform to NSCoding is going to foul up the process, so that's something to think about.

Another time I always code UIs by hand is whenever I'm using a dynamic table. If I'm creating a static table - one whose cells will basically never change - nibs are fine. For any other kind of table, and especially those that have, say, thumbnails and other resource-intensive bits, the control I get when coding by hand makes it possible to get performance you aren't going to get with nib-based table cells. For that, you do have to skip CocoaTouch and work directly with CoreGraphics, but the performance improvements you can make are worth every last line of code you have to write. For examples of table performance from projects I've worked on, see the Barnes and Noble Store (not the ebook reader) and Style.com. We built a framework for those (and other) apps, and the secret to the smooth table scrolling is that we never once used cells loaded from nibs (it's more complex than that, but skipping nibs was the first step to getting the performance you'll see in those apps).

Generally speaking, possibly the most important thing to consider when using nibs is that you need to break your UI up across files. That is, don't stick your app's entire UI into a single nib. When a nib is being loaded, it's the whole thing - there might be a view in the nib your users will rarely, if ever, see, and those get loaded just like everything else, sucking up resources for no reason. If you don't use separate nibs for each of your app's screens, it's easy to run into memory and performance issues.

To further clarify: if you have an app with five view controllers, stick each controller in its own nib. You don't want to load anything until its needed. There are exceptions to this, but that's simply how coding is - given enough time, you'll find a reason to do something "the wrong way," but the a-nib-for-each-screen approach is the way you ought to be doing it unless you have a good reason not to.

I'll leave it there - I hope it helps a little.

Just remember:

  • My informal mucking around showed that startup was faster with a nib (as long as you keep the nib as simple as possible, keeping only what you need in it).

  • After startup, performance seemed to improve for hand-coded UIs.

  • If done correctly, and if you aren't writing a game or something, nibs shouldn't result in perceptible performance issues.

  • In my experience, tables are different - they're one place I will rarely use nibs.

  • If you're using NSCoding for persisting app state, nibs can be problematic, and any workarounds probably aren't worth the effort since coding iPhone UIs by hand is relatively easy.

  • Keep your nibs as simple as possible - I can't say this enough. Wherever possible, create a nib for each screen of your app rather than stuffing your entire app's UI into a single nib.

Ok. Stopping for real this time.

Hope this helps :)

Rory Blyth