16

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 :)

Gianni Costanzi
  • 6,054
  • 11
  • 48
  • 74

2 Answers2

14

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;
}
Community
  • 1
  • 1
bryanmac
  • 38,941
  • 11
  • 91
  • 99
  • Ok... I've examined the MainWindow.xib file, referenced as the Main NIB file in the plist file, and I've seen that it has some objects defined in it, such as TestForStackOverflow App Delegate and TestForStackOverflow View Controller..I understand that they are connected to the corresponding classes, but this can not be seen from the inspector: the inspector references TestForStackOverflow App Delegate and never TestForStackOverflowAppDelegate class..I can see references to the "real" classes only if I open the MainWindow.xib file as an XML file.. BTW, I've understood where the magic happens :) – Gianni Costanzi Sep 24 '11 at 07:02
  • Just another doubt... when I create a HelloWorld View Based app the MainWindow.xib file that is automatically created is used only for the purpose of pointing to your App Delegate and View Controller classes, right? It is not used to draw the interface of your app, because you have the HelloWorldViewController.xib file for that purpose, or am I missing something? I understand that these may be obvious questions, but I'm trying to put together all the pieces of the puzzle :) – Gianni Costanzi Sep 24 '11 at 07:06
  • In the MainWindow.xib the instance of the app delegate (below the line) has a view controller target of the viewController subclass and xib that was added. So in that case the main window was just for loading. A MainWindow.m/h that inherits from UIViewController could have been added and that could have been the target ViewController. But ... – bryanmac Sep 24 '11 at 13:38
  • But, my 2 cents ... in the end interface builder is real good at layout. Controlling the aspects of each of the controls is best controlled in code because (1) I can copy/paste blocks I do all the time instead of remembering which boxes, I checked in IB and(2) it's much easier to merge. So, I do the init via code (above) and there's no magic or confusion. I still use IB for layout only. – bryanmac Sep 24 '11 at 13:40
  • related: http://stackoverflow.com/questions/7456881/interface-builder-xib-or-code-when-merging-in-a-team-environment – bryanmac Sep 24 '11 at 13:41
  • I think I've made a bit of confusion because I did not look very well into the Inspector when looking at the TestForStackOverflow App Delegate object in the MainWindow.xib file, I'll give another look as soon as the Time Machine restore will finish (I decided to do a clean re-install of Lion).. Thank you very much for your help, I think I'll go for the Interface Builder in the first phases of learning and then do as you suggested after other aspects of the development becomes clearer.. Btw, I'd like to understand where the magic comes from, so many thanks ;-) – Gianni Costanzi Sep 24 '11 at 16:41
4

1) To be simple, when UIApplicationMain() is called,

  • you application .plist is found,
  • the key "Main nib file base name" is looked up,
  • this XIB is opened,
  • The object that supports the UIApplicationDelegate protocol is instantiated and used as the application delegate

2) They are set in the XIB, you can view them if you

  • open the main XIB,
  • select the AppDelegate object,
  • open the Connections inspector for this object,
  • look into the Outlets section

3) You are right, they are created automatically by the compiler. It makes the code more readable by having less line, and more easy to refactor having only one place the property is declared.

Hope it helps!

Pierre-David Belanger
  • 1,004
  • 1
  • 11
  • 19