How do I access my Application Delegate's window accessor method from another object?

VectorVictor picture VectorVictor · Apr 23, 2011 · Viewed 20.4k times · Source

As mentioned before - I'm an Objective-C newbie of the first order but having read 4 physical books on the subject and a bucket-load of ebooks and documentation I still can't find what I'm looking for.

I have a top-level content view controller that wants to configure its view property from the physical dimensions of the window property of the application delegate. This is something that several people have already asked questions on. ([UIScreen mainScreen] doesn't cut it for reasons already aired many times before on this forum). Therefore, the logical approach would be for the content view controller to read the frame of the application delegate's window. Now, the only answer I've found that comes close to this is to use [[[UIApplication sharedApplication] window] frame] - however, this only works once the window property has been made keyAndVisible. The content view controller needs to read the app delegate's window property before it gets to makeKeyAndVisible. The code goes in this order....

App Delegate:

- (BOOL) application: (UIApplication *) application didFinishLaunchingWithOptions: (NSDictionary *) launchOptions {
// This next line is a test window frame for R&D purposes....
    [self setWindow: [[UIWindow alloc] initWithFrame: CGRectMake(0.0f, 20.0f, 320.0f, 320.0f)]];

    if ([self window]) {
        contentViewController = [[ContentViewControl alloc] initWithNibName: nil bundle: nil]; // Content view controller instantiated here

        if (contentViewController) {
            [[self window] addSubview: [contentViewController view]];
            [[self window] layoutSubviews];
            [[self window] makeKeyAndVisible];  // Window made key and visible here
            return YES;
        }
    }

    return NO;
}

In my content view controller's initWithNibName: nil bundle: nil method I have the following test code...

- (id) initWithNibName: (NSString *) nibNameOrNil bundle: (NSBundle *) nibBundleOrNil {
    self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil];

    if (self) {
        NSLog(@"%@", NSStringFromCGRect([[[UIApplication sharedApplication] keyWindow] frame]));
        // This does not work.
    }

    return self;
}

This does not work due to the fact that App Delegate's window is not yet key and visible. So, my question is thus; What is the name of my App Delegate Class' instance? I know the App Delegate's Class name defaults to myApplicationNameAppDelegate but I'm after the instance name. I want to replace the call to [[UIApplication sharedApplication] keyWindow] by something like;

[myAppDelegatesInstanceName window].

Expanding this a little, how does one access methods in other target objects that are not scope descendants of the object doing the querying?

Like I said, I'm a total noob to all of this and this is probably another dumb noobie question but it's one that nobody yet appears to have answered in a simple way.

(Procedurally - my home turf - there are a plethora of ways to get the window stuff down into other levels of scope ranging from making the window globally accessible to the whole program suite to passing it down as a specific parameter through the various function hierarchies - but this Objective stuff seems to depart from established, procedural practice).

If anyone can help, I'd be really grateful. This stuff is definitely not intuitive! V.V.

Answer

Ole Begemann picture Ole Begemann · Apr 23, 2011

You can access the app delegate through the singleton UIApplication instance:

[[[UIApplication sharedApplication] delegate] window];

This is a special case, though, because you can access an object (the UIApplication instance) whose delegate you know is the object you want to access. The general case:

Expanding this a little, how does one access methods in other target objects that are not scope descendants of the object doing the querying?

You need to pass a reference to the target object to the object from which you want to access it. This is sometimes necessary but it also means that you introduce a tight coupling between these two objects, which you generally want to avoid if you can. So think about each case and see if there are other possible designs.