PrEV
Thoughts from a NeXTStep Guy on Cocoa Development

Demystifying iPhone App Startup

Jan 06, 2009 by Bill Dudney

In conversations about iPhone development I've noticed that many people, despite being able to get a lot of stuff done in their iPhone projects, feel like the way it all works is magic. I'm going to try to put together a couple of articles about how things work in an attempt to demystify the areas that seem to be the most 'magical'. In this first article I'm discussing application startup. Chaining NIB files will likely be the next article, if you have other ideas I'd be happy to entertain them, email or comments are a fine way to suggest.

I know, getting rid of the magic might be disappointing, but it will make you a better iPhone developer in the end so its worth it :)

Application Startup

To follow along with the discussion, fire up Xcode and create a new view based application called 'Hello'. All the code in this post is pulled from the instantiation of the View-Based Application template.

Like many other C based languages (such as Java, .NET and many others) Objective-C uses the main function as the entry point. Fortunately every template that ships with the iPhone SDK has an implementation of the main function built in. Here is the code for the main method.

int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; return retVal; }

As you can see there is not too much here, four lines of code is all it takes to kick off a Cocoa Touch application. Let's take a look at what is happening on each line of code. On the first line the 'top-most' autorelease pool is being created, this is a crucial part of the reference counting memory management scheme for Objective-C objects. I don't have time to cover retain counting in this post but Apple has some decent docs here, and my screencast here has some additional content.

The next line of code invokes the UIApplicationMain function. This function is the source of much of what appears to be magic. The function takes four arguments, the first two are the same arguments that the OS passes into the main function. The next two arguments take a bit more to explain.

The third and fourth arguments are the class names of the principal class, which should be a subclass of UIApplication, and the delegate class, which should implement the UIApplicationDelegate. If you pass in these two class names they will be used to create instances of the two classes, and then the instance of the delegate class will be set as the delegate of the application object.

Since we are passing 'nil' for the final two arguments the function expects the Info.plist to specify a value for the NSMainNibFile key that notes a nib file as the 'main nib file'. This nib file is expected to have the File's Owner's class be UIApplication and have its delegate set to another object in the same nib file. We will look at the nib file in a moment. In the mean time here is the relevant bit out of the Info.plist file.

<key>NSMainNibFile</key> <string>MainWindow</string>

Back to main, after the UIApplicationMain function returns (which won't be until the application is quitting) the pool is released. The final line where we return the integer we got from UIApplicationMain lets the OS know how the application ended. On the iPhone the return value is largely ignored and UIApplicationMain always returns zero anyway perferring instead to handle error cases via a Unix exit function call. So now you have seen the basic startup code for every iPhone application. Now lets look at in detail at the main nib file and how UIApplicationMain works with it to build the running version of your application.

Main NIB File

Nib files are serialized graphs of objects, the objects that make up your application's user interface. Another way to think about a nib file is like a freeze dried copy of your app's user interface. The objects (like text fields, buttons and labels) that you add to the UI in Interface Builder get written into the nib file. When the nib file is loaded all those objects are reconstituted from the file into real objects.

The objects in the document window are also written to the file, mostly anyway. There are a few exceptions and one that is particularly interesting. The 'File's Owner' object is a proxy to an object that is passed into the nib loading method loadNibNamed:owner: as the second argument. So instead of the File's Owner being in the nib file, a proxy to it is in the nib file and a real object is substituted when the nib file is loaded.

The cool thing about this substitution is that the connections and other configuration we do to the File's Owner is applied to the real object when it is passed in. Let's open up the nib file and take a look, open up the MainWindow.xib. Here is a screenshot of the document window.

Select the File's Owner and bring up the Connections inspector with Command-2. Notice that the inspector (the fig below is a screen shot of it on my box) you can see that the delegate is set. That connection is what sets the delegate of our application object, despite the application object being created in UIApplicationMain. I hope that makes sense because it is so important to understanding many of the other ways that we use nib files, especially with view controllers.

The next question to ask is 'how does Interface Builder know that the File's Owner object has a delegate outlet?' If you keep the File's Owner selected and bring up the Identity inspector (Command-4) you will see something that looks like the next screen shot. So it's not magic, it's not some interesting naming scheme. We tell Interface Builder the class of the File's Owner, when we do that IB looks at the class and gives us access to its outlets and actions so that we can make these connections.

Now that we have looked at the configuration of the File's Owner lets look at the delegate. Select the object called 'Hello App Delegate' (top right hand side in the object view from the screen shot above) and bring up the Identity inspector with Command-4. Notice the class is set to HelloAppDelegate. This object is in the nib file so we never have to create an instance, the one that runs in our application comes from loading this file. See the difference between the File's Owner? We configure both in Interface Builder, but one is created outside the nib file and the other comes from inside the nib file and is reconstituted when the nib file is loaded.

The Application object sends its delegate all sorts of interesting messages (look up UIApplicationDelegate for a full list). In our case though we are interested in the applicationDidFinishLaunching: method since that is the only method implemented for us by the template. Here is the code for the method.

- (void)applicationDidFinishLaunching:(UIApplication *)application { [window addSubview:viewController.view]; [window makeKeyAndVisible]; }

Not much code here, but this is what makes the application 'our' application. The first line puts the content of our view controller into the window, and the second makes it visible and ready to start processing events. Where does this window and view controller come from? Well the nib file of course, who'd want to write all the code to create these objects by hand, and more importantly who'd want to maintain it. Back in Interface Builder, select the 'Hello App Delegate' object and open the connections inspector (Command-2). You should see something that looks like this screen shot.

In the 'Referencing Outlets' you see the incoming connection from the File's Owner. In the top list you see where our view controller and window come from. Move your mouse over the window connection and look in the document window, notice that the 'Window' object is highlighted. That little bit of Core Animation magic is what tells you the objects at both end of the connection. The viewController is connected to the object called 'Hello View Controller'. And these two connections are where the window and view controllers come from in the applicationDidFinishLaunching: method.

Wrap Up

Finally, to recap what we have seen so far this diagram shows the basics of what happens during app startup. The main function is invoked by the OS, that fires off the UIApplicationMain function which creates the application object, looks in the Info.plist file for the 'main nib' file and loads that nib file passing the newly created application object in as the File's Owner. The connections made in IB are then applied to the File's Owner and when the application finishes launching the applicationDidFinishLaunching: delegate method is invoked which causes our view controller's view to become visible and ready to take events.

I hope this has helped demystify how iPhone applications start up. If you'd like to grab my copy of the code (only slightly modified from the template) you can grab it here.



Comments:

The [pool release]; could even be removed since there's no real point to freeing all autoreleased objects right before the whole memory space for the application is freed.

Posted by Devon on January 06, 2009 at 07:22 PM MST #

Thank you for this. I just can't write code without knowing why I'm writing it -- i need to know how it all fits together and this has aided that quest.

Posted by Steve on January 07, 2009 at 04:51 AM MST #

My thanks as well. "Who would want to create all those objects?" We are only talking about 4 of them (UIApplication, the app delegate, view controller, and a window). The code for it is quite small (and could be auto generated like all the other boilerplate code in main.m).

This is why I don't like IB. It is a form of learned helplessness, a reliance on poorly understood "magic". Despite reading numerous Apple docs, I never understood this.

Posted by steve on January 18, 2009 at 05:03 AM MST #

Hi Steve,

Well the thing about IB is that like any other tool it can lead to learned helplessness or it can make your life easier. I prefer to learn what its doing and use the tool.

Beside this is a really really simple application. If you have a largish app you can save hundreds of lines of code building with IB instead of in code.

Thanks for the comment!

Posted by Bill Dudney on January 18, 2009 at 05:03 AM MST #

Hey Bill,

Thanks for the article. My one suggestion would be to show the non-IB way to do it (not that we would want to of course) but that might help to demystify it even more. So, same post, longhand version.

Thanks again!

Posted by Judd on January 23, 2009 at 12:58 PM MST #

I have over 100 views in my app, IB is a real time saver.

Posted by Rob on January 29, 2009 at 12:19 PM MST #

Hi Bill,

Great article.
A follow up article on how to create a simple app without using any NIB files in the project would be useful. I use a simple cross-platform GUI layout file that also works on Symbian and Windows Mobile.

BTW, your iPhone SDK Book is fantastic.

Cheers,
Keith.

Posted by Keith on February 10, 2009 at 08:48 AM MST #

Bill,

Thanks for the article. I'm looking forward to your (and Chris/Marcel's) upcoming book release, btw.

In my experience, UIApplicationMain() never actually returns, even though the official Apple documentation says that it should. Instead, the UIApplication _terminateWithStatus method (non-published) simply does exit(0) after calling your delegate's applicationWillTerminateMethod. I've had other developers confirm this behavior on their machines.

If you see this behavior, too, it might be worth editing your post so that readers aren't mislead into thinking that [pool release] will be called.

Posted by Clint Harris on February 18, 2009 at 03:18 PM MST #

This is also described in Your First iPhone Application > Creating Your Project > Application Bootstrapping:

http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhone101/Articles/chapter_3_section_3.html

Posted by mmalc on February 19, 2009 at 06:54 AM MST #

Just reporting a typo: In the graph above the .plist excerpt, "expect" s.b. "expected".

Being newish to the whole Cocoa world, it took me awhile to wrap my head around IB. My first iPhone app's UI was entirely hand-coded -- tedious, but comfortable (ah, code!). But I'm now an IB convert.

Posted by Danny Goodman on February 19, 2009 at 06:54 AM MST #

Thanks Bill: Been programming for a hundred years (Assembly and c). the IB seems like something I should know, and your article will help steel the nerves of an old codifile. Thanks again.

Posted by Pete gregorio on March 10, 2009 at 04:49 PM MDT #

Thanks. I'm on my fourth or so day of iPhone development (no previous exp of Cocoa/IB/ObjC) and while it's easy to see the benefit of IB in the long run, for larger apps and what have you, it is incredibly frustrating not to know how early app execution works or be able to understand the program flow. I think that from a pedagogical viewpoint (at least for me...), the IB* is not brilliant. Having had it introduced at a stage later than the Hello World app** would have made me progress faster. Like: "OK, now, all that tedious coordinate and background color stuff we did in lesson 1 to 5 for the sake of understanding, it can be automated! Yay!"

* or maybe my antagonist here is actually the nil value passed to UIApplicationMain. It would have helped loads just to provide my own AppDelegate explicitly and created the main window programmatically (while at the same time used IB for eg ViewControllers).

** as given by Apple intro docs - not commenting on any books here... :)

Posted by Niklas Björnberg on July 28, 2009 at 07:35 AM MDT #

I read your post to learn something about the "File's Owner" object. What a bizarre name! What file does it own? Am I not the owner of files that I create? Or are we not talking about the usual .txt, .pdf etc. files? As a newbie, I'm frustrated that I could not get the keyboard to dismiss after text was input into a text box. I found tons of posts about this, but no sure-fire solutions. I used IB to inspect everything up, down, and sideways. I added code that was recommended, but the dumb keyboard will not go away. This whole idea of delegating this to that seems like an exercise in chasing your tail. Some stuff ought to just work, without connecting so many dots. The first improvement to IB would be to make it large enough to be seen and not to truncate text.

Posted by Scott Pendleton on October 20, 2009 at 04:39 AM MDT #

Hi Scott,

Sorry your finding keyboards mystifying. I know that it might seem that there is an easier way when you first get started and you are right of course. However I promise that once you learn your way around the way things work will make sense.

File's Owner is the owner of the nib file and its contents, would be good to know why you would think it has anything to do with a text file.

Good luck!

Posted by Bill Dudney on October 20, 2009 at 04:39 AM MDT #

Thanx for this post...
i enjoyed really

Posted by Balu on May 24, 2010 at 01:58 PM MDT #

Very insightful and very helpful.

Posted by Richard on June 08, 2010 at 06:16 AM MDT #

Awesome article. Thanks for putting it up

Posted by venkat on August 15, 2010 at 09:41 PM MDT #

Very nice post, thank you!

Posted by Masum on October 02, 2010 at 08:21 AM MDT #

Thanks; great article!

Posted by onthegrid on January 09, 2011 at 07:58 AM MST #

By far the best post that removes the magic behind how the 'nib' runtime works. Coming from .NET, this design is hard to grasp.

Posted by Kevin Ramsaur on March 20, 2011 at 06:31 PM MDT #

Post a Comment:
  • HTML Syntax: Allowed