[MonoTouch] Startup times: nib vs. nib-less [was Re: Can I show splash image within a second?]
Rory Blyth
lists at rory.me
Fri Nov 27 20:55:09 EST 2009
[Note: Like most of my forum posts, emails, comments, etc., this is a little long - apologies. It ends up being about: 1. Apple's explanation of how nibs function, 2. Atypical uses for IB, 3. Whether it truly is a bad idea to use a tab bar controller as your main controller, 4. Advantages of coding UIs by hand, 5. Performance implications of nibs versus hand-coded UIs...]
From Apple's documentation:
"When a nib file is loaded into memory, it is an all-or-nothing endeavor. The nib-loading code has no way of knowing how many objects are in the file or which ones are important, so the entire file must be loaded into memory. From this in-memory data, individual objects are then instantiated. For Cocoa and iPhone applications, all of the objects in the nib file are instantiated right away so that outlet and action connections can be reestablished. If your application uses only some of the nib-file objects initially, having all of the objects in memory is a waste."
If I have a nib, it'll usually be just that: *a* nib. I'll use it for laying out top-level navigation. After that, I'll use Interface Builder to prototype, though I'll ultimately code everything but that top-level nib UI by hand. I find it especially helpful when performance (not just load time) is an issue, and I can use IB to design UI elements, then copy down the dimensions and layout info so I don't have to do a bunch of guessing when writing CoreGraphics code. I'm not into the whole code-the-UI-then-find-out-it's-a-pixel-off-here-so-I-change-a-value-then-rebuild-then-test-then-it-turns-out-it-was-actually-a-different-pixel-so-I'm-just-going-to-start-randomly-changing-dimension-values-until-this-sucker-works thing. IB is *very* helpful there even when you don't use nibs.
But I have, in demos, used multiple nibs for convenience (though it wasn't convenient until I actually *learned* IB - before that, it was pain).
Regarding the use of tab bar controllers as main controllers and associated issues... I've never experienced that. The only problem I ever had was the one following a new release of Apple's dev tools - they fiddled with something, and my stuff broke. It was working for months before that. And it was far more convenient than doing it by hand (even though doing it by hand is trivial).
I'm not even sure how I'd use a tab bar controller *without* it being my main controller. It might be habit, but... I don't see how else you'd do it if you're writing a tab bar based app.
When it comes to coding by hand, I override loadView (or "LoadView" in MT) and just do it to it. There are many reasons for doing this - the most important, for me, have been:
1. Performance (in some situations - that's a whole other thread).
2. Control over archiving - I've had a far easier time with NSCoding when coding my UIs by hand. When I was getting started with iPhone development, I went with what seemed the easiest route (doing as little work by hand as possible), but then you try to archive a view controller with a view that has a UIImage in it somewhere and everything breaks (because UIImage doesn't conform to NSCoding). UIImage is pretty common, and there are plenty of classes that have their own internal instances of UIImage that you can't get to (at least not without some awkward coding), and that can totally foul up what would otherwise be a simple operation. When I subclass a view controller, override loadView and the NSCoding methods, life becomes much easier, and I end up with a view controller hierarchy I can freeze-dry and reconstitute with very little code (I've found NSCoding to be the easiest way to write apps that behave according to Apple's design guidelines - all the state saving that needs to be done when someone quits your app and all the restoration that needs to be done when they return).
I'm not saying it's necessary to do this - for some apps, it doesn't make sense to return to the point the user was at when they quit the app (though the AppStore app is *not* one of them, yet it totally breaks a bajillion of Apple's own guidelines - that, too, is another thread - one where I pull my hair out and curl up in the fetal position and cry in the corner until I feel better). But for the apps where it's necessary, the easiest state-saving method I've used is implementing the NSCoding protocol in in my models and view controllers.
Finally... more nib vs. hand-coding...
For performance (and I'm whipping up some demo code to test this), it looks like my previous email was probably correct (at least for MT - I'm writing the same demo apps using Apple's stack just to compare):
1. For fastest startup, even though it's counterintuitive (to me, anyway), start your app with a nib.
2. For fastest performance after your app has started, use hand-coded UIs.
I'm putting the demo code together in a sloppy, informal way, but it'll make it easy for people to see the differences without having to learn how to use Instruments and other profiling tools.
There. That's probably enough tangents for one email :)
- Rory Blyth
On Nov 24, 2009, at 5:48 PM, Ed Anuff wrote:
> I believe that the overhead of NIB's doesn't come from the loading of the NIB file itself. As you point out, it's compiled to a binary file. If using NIBs actually had a lot of inherent overhead, it would be trivial to create a tool like the MonoDevelop code-behind to compile them to C# code that you could hand edit (which actually, would be pretty useful). I think that the issue is the lazy instantiation of views loaded from NIBs isn't all that lazy and always ends up instantiating more than you probably need at startup. You can see this if you put logging code in your viewDidLoad methods. Now, one approach is to break your UI into multiple XIBs. However, if you're using a UITabBarController as your main controller, which isn't all that uncommon, you're going to find that nothing works quite as expected, which is why most people recommend against it. If you're coding things by hand, you're probably only going to get the benefits if you do a lot of UI construction in your viewWillAppear methods. However, I'd take any recommendations along these lines with a grain of salt and test any approach empirically.
> _______________________________________________
> MonoTouch mailing list
> MonoTouch at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/monotouch
More information about the MonoTouch
mailing list