My last set of posts were an introduction into Objective-C and a look at the NSObject interface. In this post, I’m digging into iPhone applications and looking at all of the parts and how they really execute on the iPhone.
The start of any application on any platform is the application entry point function. In C, C++, and Objective-C applications, this entry point function is known as main. When a new iPhone application is created in Xcode, Xcode will create the main method automatically in the main.m file:
#import
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retval = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retval;
}
This is a pretty simple function. The main method accepts two parameters. argc is the number of arguments that were passed to the application on the command line. argv is an array of strings containing the text for the command line arguments. Note that the strings are ASCII C null-terminated strings and not Objective-C NSString objects. Now I’m not sure how the iPhone specifies command line arguments, so I don’t know if these two parameters will ever be used.
The first line of the method allocates and initializes a NSAutoreleasePool object. If you’ll remember my earlier post on NSObject and memory management, NSAutoreleasePool manages a memory pool for the process. All objects that are allocated in memory by the application will be registered with the pool. When the pool object is released on the third line of the method, all of the objects that are registered with the memory pool will be destroyed.
On the second line of the function is a call to UIApplicationMain(). This function is an iPhone OS function that will run the iPhone application. The function definition looks like this:
int UIApplicationMain(
int argc,
char *argv[],
NSString *principalClassName,
NSString *delegateClassName);
The first two parameters for the UIApplicationMain function are the parameters that are passed to the main function. The third parameter, principalClassName, is the name of the application class. Notice that the main method passed the nil value for the principalClassName parameter which causes UIApplicationMain to default to use UIApplication as the application class.
The fourth parameter is the name of the delegate class for the application. The delegate class is a class that supports the UIApplicationDelegate protocol (see below). Again, notice that main passes nil for this parameter. When a nil value is passed for the name of the delegate, the UIApplicationMain method will resolve the delegate object from the Info.plist file.

In the screen shot above is the Info.plist file for my new project. The line that we’re interested is the last line that shown the Main nib file base name property. This property is the base name of the nib file that the UIApplicationMain function will use to initialize the application and set the application delegate.
The next file that we will look at will be that nib file: MainWindow.xib. Looking at the MainWindow.xib file, the following objects exist:
- File’s Owner
- First Responder
- My application’s app delegate
- Window
- Navigation Controller
The File’s Owner object is set to be a UIApplication object, which is what we need. The interface for the UIApplication class is shown below:
@interface UIApplication : NSObject
@property (nonatomic) NSInteger applicationIconBadgeNumber;
@property (nonatomic) BOOL applicationSupportsShakeToEdit;
@property (nonatomic, assign) id delegate;
@property (nonatomic, getter=isIdleTimerDisabled) BOOL idleTimerDisabled;
@property (nonatomic, readonly) UIWindow *keyWindow;
@property (nonatomic, getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
@property (nonatomic, readonly) CGRect statusBarFrame;
@property (nonatomic, getter=isStatusBarHidden) BOOL statusBarHidden;
@property (nonatomic) UIInterfaceOrientation statusBarOrientation;
@property (nonatomic, readonly) NSTimeInterval statusBarOrientationAnimationDuration;
@property (nonatomic) UIStatusBarStyle statusBarStyle;
@property (nonatomic, readonly) NSArray *windows;
+ (UIApplication *)sharedApplication;
- (void)beginIgnoringInteractionEvents;
- (BOOL)canOpenURL:(NSURL *)url;
- (UIRemoteNotificationTypes)enabledRemoteNotificationTypes;
- (void)endIgnoringInteractionEvents;
- (BOOL)isIgnoringInteractionEvents;
- (BOOL)openURL:(NSURL *)url;
- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)type;
- (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event;
- (void)setEvent:(UIEvent *)event;
- (void)setStatusBarHidden:(BOOL)hidden animated:(BOOL)animated;
- (void)setStatusBarOrientation:(UIInterfaceOrientation)interfaceOrientation
animated:(BOOL)animated;
- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated;
- (void)unregisterForRemoteNotifications;
@end
In a future post, I’ll come back and start taking a look at some of the features of the UIApplication class, but here’s the important things to know. There’s only a single instance of the UIApplication class per application. It’s a singleton. The reference to the singleton object can be retrieved using the class-scoped method sharedApplication. For example, to get a reference to the UIApplication object from anywhere in an application, the following code would work:
UIApplication *application = [UIApplication sharedApplication];
The UIApplication object processes events for the application and forwards the events to other components or event handlers. Some of the events that affect an application in general are sent to an object called the application delegate and is referenced by the UIApplication.delegate property. An application delegate object implements the UIApplicationDelegate protocol:
@protocol UIApplicationDelegate
@optional
- (void)application:(UIApplication *)application
didChangeStatusBarFrame:(CGRect)oldStatusBarFrame;
- (void)application:(UIApplication *)application
didChangeStatusBarOrientiation:(UIInterfaceOrientation)oldStatusBarOrientation;
- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo;
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
- (BOOL)application:(UIApplication *)application
handleOpenUrl:(NSURL *)url;
- (void)application:(UIApplication *)application
willChangeStatusBarFrame:(CGRect)newStatusBarFrame;
- (void)application:(UIApplication *)application
willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation
duration:(NSTimeInterval)duration;
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (void)applicationDidFinishLaunching:(UIApplication *)application;
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;
- (void)applicationSignificantTimeChange:(UIApplication *)application;
- (void)applicationWillResignActive:(UIApplication *)application;
- (void)applicationWillTerminate:(UIApplication *)application;
@end
The application delegate protocol defines many methods, all of which are optional. This protocol is implemented by a delegate class that will handle the lifecycle events that are reported by the UIApplication object. If you’ll remember, however, back in our call to UIApplicationMain, we didn’t provide a delegate object. We instead passed in a nil object and the iPhone OS looked to our MainWindow.xib file to get an answer. The delegate is actually created and attached to the UIApplication object in the nib. Inside the nib file, there’s an application object delegate that is created by the project template. That application delegate object is then attached to the UIApplication.delegate property using a connector in Interface Builder.
Given this connection, an iPhone developer can use the generated application delegate class to implement the lifecycle event handling such as applicationWillTerminate to save the application’s state and release resources before the application is unloaded. Special initialization and start-up logic could be placed in the application:didFinishLaunchingWithOptions: method.
For example, I created a navigation view application and Xcode generated an initial application delegate class like this:
@interface MyAppDelegate : NSObject {
UIWindow *window;
UINavigationController *navigationController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@end
@implementation MyAppDelegate
@synthesize window;
@synthesize navigationController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
- (void)dealloc {
[navigationController release];
[window release];
[super dealloc];
}
This code shows that the application delegate has two properties. The first, a UIWindow object, is the window that hosts the user interface for the iPhone application. The second, a UINavigationController object, is used to control the navigation between views of the application.
The application delegate implements only one of the optional UIApplicationDelegate methods: applicationDidFinishLaunching:. This method is called by the UIApplication object when the application first starts. The code in that method will display the main view for the application in the window and will display the window in the iPhone display.
In the MainWindow.xib file, I also see two additional objects: a window and a navigation controller object. These objects are linked by connectors in Interface Builder to the window and navigationController properties on my application delegate.
At this point, I’ve followed the execution of my iPhone program from the main function to the UIApplicationMain function that starts the execution of the iPhone user interface. From there, I’ve shown how UIApplicationMain will use the MainWindow.xib file to create the application delegate object and attach it to the UIApplication.delegate property. Finally, I just briefly started to cover the role of the application delegate object. In a future post, I’ll start exploring in more detail more of the properties and methods on the UIApplication class and the UIApplicationDelegate protocol.