Where is your Application Delegate set and who initializes its window and viewController properties?

Gianni Costanzi picture Gianni Costanzi · Sep 24, 2011 · Viewed 12.4k times · Source

I have a very newbie question about IOS apps... If I create a new View Based Application called TestForStackOverflow, Xcode automatically creates code like this for the TestForStackOverflowAppDelegate.h:

@class TestForStackOverflowViewController;

@interface TestForStackOverflowAppDelegate : NSObject <UIApplicationDelegate>

@property (nonatomic, retain) IBOutlet UIWindow *window;

@property (nonatomic, retain) IBOutlet TestForStackOverflowViewController *viewController;

@end

and the following in TestForStackOverflowAppDelegate.m:

#import "TestForStackOverflowAppDelegate.h"

#import "TestForStackOverflowViewController.h"

@implementation TestForStackOverflowAppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

[...]

Here come my questions:

1) where is the TestForStackOverflowAppDelegate class set as delegate for the current application? Is it done "automagically"? I've seen that the main.m source file contains only the following code:

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

Shouldn't it set the application delegate class in the fourth parameter of the UIApplicationMain function invocation?

2) where are the window and viewController properties of TestForStackOverflowAppDelegate class being set?

3) this may be trivial, but why do we have synthesize window = _window, without having an instance variable called _window in TestForStackOverflowAppDelegate interface? I've seen that you can declare @properties without having the corresponding iVars in the class interfaces (maybe they are automatically created by the compiler), but is it a good practice or should you always create the corresponding iVars in your classes?

Excuse me for the very long message, I just hope I've not written a too obvious question since here in Italy is late night and I'm very tired.. but when these questions come into my head, I can't wait for the solution :)

Answer

bryanmac picture bryanmac · Sep 24, 2011

How is the app delegate class loaded?

In your -info.plist file there is a key named "Main nib file base name" and has a view something like MainWindow.xib. In that xib file, there's a file's owner proxy object and it has a delegate set to the app delegate class.

Open that XIB in the designer. Notice the File's Owner object at the top, context click on it and look at the delegate object. Now look at the objects in the design below the (XCode 4) line - you should see the app delegate object there.

Where is the window and viewController for the appDelegate set?

Look in the designer and context click on the app delegate object below the (XCode 4) line. The window and viewController target is tied there.

_window iVar

It's automatically provided for you. Not clear to me whether it's inherited or generated by the compiler.

Here's more on _ iVars: Why rename synthesized properties in iOS with leading underscores?

If you chose to do the equivalent in code:

remove plist xib reference main.m: pass name of delegate

int main(int argc, char *argv[])
{
    int retVal = UIApplicationMain(argc, argv, nil, @"HelloViewAppDelegate");

In app delegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    CGRect screenBounds = [[UIScreen mainScreen] applicationFrame];
    CGRect windowBounds = screenBounds;
    windowBounds.origin.y = 0.0;

    // init window
    [self setWindow: [[UIWindow alloc] initWithFrame:screenBounds]];

    // init view controller
    _mainViewController = [[MainViewController alloc] init];

    [[self window] addSubview:[_mainViewController view]];

    [self.window makeKeyAndVisible];
    return YES;
}