views:

47

answers:

4

I'm trying to have my view hierarchy loaded through calls to loadNibNamed.

For a single nib, in my ApplicationViewController : UIViewController :

- (void) loadView {
    [super loadView];
    [[NSBundle mainBundle] loadNibNamed:@"ApplicationViewController" 
                                  owner:self options:nil];
}

But then in SubViewController : ApplicationViewController :

- (void) loadView {
    [super loadView];
    [[NSBundle mainBundle] loadNibNamed:@"SubViewController" 
                                  owner:self options:nil];
}

When I init SubViewController, the view only contains its own nib file, how do I get the ones from super too ?

I've tried to insert the objects returned from the call to NSBundle, back into the calling UIViewController's own view hierarchy, but this didn't work out and some casting issues prevent me from being able to debug this...

A: 

First of all, I generally load Nibs with something like the following, then assign that controller to a retained member of its parent controller...

self.myViewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];

So each view controller loads the contained views' controllers. Then you may or may not have to explicitly add the controllers view (myViewController.view) to the parent with a call to:

[window addSubview: myController.view];

You might want to check out Apple's QuartzDemo or UICatalog for an example of code that loads lots of children view controllers, although it adds it to a list instead of a view.

samkass
I've edited my question to emphasize the subclass situation I'm having, which would prevent me from doing this, wouldn't it?
julien
+1  A: 

What is probably happening in your example is that in both nib files you are setting the view Outlet. What happens then is the second loaded nib file will overwrite the value of the view property set by the first nib file:

@implementation SubViewController

- (void) loadView
{
    [super loadView];
    // at this point, self.view points to the view loaded from
    // ApplicationViewController.nib
    [[NSBundle mainBundle] loadNibNamed:@"SubViewController" 
                              owner:self options:nil];
    // but at this point, self.view is overwritten with the view from
    // SubViewController.nib
}
...
@end

So what you could do is this: in your SubViewController class, declare a different outlet, say like this:

@property (nonatomic, retain) IBOutlet UIView* viewForSubController;
//you can probably think of a better name for it.

and in your xib file, don't have the view property set, but instead have the viewForSubController set. And then in the loadView do something like:

@implementation SubViewController

- (void) loadView
{
    [super loadView];
    // at this point, self.view points to the view loaded from
    // ApplicationViewController.nib
    [[NSBundle mainBundle] loadNibNamed:@"SubViewController" 
                              owner:self options:nil];
    // now, self.viewForSubController points to the view loaded from
    // SubViewController.nib

    // so now we can do this:
    [self.view addSubview: self.viewForSubController];
}
...
@end

Or something along those lines.

filipe
Exactly what was happening, I've managed to get it to work by adding an IBOutlet for each level of the view hierarchy, might feel bit hacky, but I'm pleased with it so far...
julien
A: 

You really shouldn't be loading from a nib in loadView. The purpose for overriding that method is to create your own views programmatically. You could call initWithNibName: from the standard init, but it sounds like you're trying to compose two views together. I don't think subclassing is going to do that the way you want. You can have the parent view load the child view and add its view property to the parent view hierarchy. Is that what you're trying to do?