4

I created a custom view in interface builder with a few buttons in it. I created a class in code for it as the "Files owner" to connect the buttons to action methods.

How do I use this class then?

I cannot just do it like this...

StartScreen *ss = [[StartScreen alloc] initWithFrame: ...];
[self.window.contentView addSubView: ss];
...

because this only produces an empty view. (of course: the StartScreen class doesn't know anything about the nib file yet.)

What I want to do is something like:

StartScreen *ss = LoadCustomViewFromNib(@"StartScreen");
[self.window.contentView addSubView: ss];

or maybe i have to say something like

[self iWannaBeANibWithName: @"StartScreen"];

in the constructor of StartScreen?

pls help... (btw I am developing for Mac OS X 10.6)

Michael
  • 6,451
  • 5
  • 31
  • 53

2 Answers2

4

One option is to make StartScreen a subclass of NSViewController, maybe changing its name to StartScreenController. This is a potentially more modular solution in case you have IBActions in your nib file and/or you want to place view controlling code in its own class.

  1. Declare StartScreenController as a subclass of NSViewController
  2. Declare IBOutlets in StartScreenController if needed
  3. Set the nib file’s owner class to be StartScreenController
  4. Connect the file’s owner view outlet to the view object, and other outlets if needed

Then:

StartScreenController *ss = [[StartScreenController alloc] initWithNibName:@"nibname" bundle:nil];    
[self.window.contentView addSubView:ss.view];
…

If you’re not using garbage collection, don’t forget to release ss when it’s not needed any longer.

  • well, this gives me an error: `-[NSViewController loadView] loaded the "StartScreen" nib but no view was set.` but I solved the problem finally: i directly initialize and instantiate a nib and traverse its top level objects to find the view object. NSNib *nib = [[NSNib alloc] initWithNibNamed:@"StartScreen" bundle:nil]; StartScreen *ss = [[StartScreen alloc] init]; NSArray *aa; BOOL ok = [nib instantiateNibWithOwner: ss topLevelObjects: &aa]; aa contains two objects, and one is the view object that I need. – Michael May 16 '11 at 00:02
  • @Michael You’ve got that error because you’ve missed step 4: connect the `view` outlet. –  May 16 '11 at 00:04
  • thanks for the help! but I think this is more complicated than it should be. I solved it in a different way: I created my own view controller class (a subclass of NSObject) that does the nib loading stuff automatically. And it also connects the view to an instance variable. I just have to do `StartScreen *ss = [[StartScreen alloc] init];` and `[self.window.contentView addSubview: ss.view];` in the app delegate and everything works. There's not even the need to specify the nib name. -init just calls +nibName to get the nib name, and my default implementation just returns the class name. – Michael May 16 '11 at 14:00
  • @Michael You’ve essentially duplicated what `NSViewController` already does for you, so I’m not sure why using `NSViewController` is more complicated. Anyway, whatever works for you! –  May 16 '11 at 21:27
2

The Nib loading functions are part of the NSBundle class. You can use it like this...

@implementation StartScreen
- (id) init {
    if ((self = [super init])) {
        if (![NSBundle loadNibNamed:@"StartScreen" owner:self])
            // error
        // continue initializing
    }
    return self;
}

See NSBundle Additions reference.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • It didn't work for me yet, but I think I identified the problem. I have made the StartScreen class a subclass of NSView. But I think it should be a subclass of NSObject, right? But how do I display this view then? I mean, I cannot just call [self.window.contentView addSubView:] in the app delegate, because I don't see a view object, do I? – Michael May 15 '11 at 21:20
  • (I suspect that it shouldn't be a subclass of NSView because you used -init as the constructor and not -initWithFrame:) – Michael May 15 '11 at 21:32
  • I now call the loadNibNamed: method in the -initWithFrame: constructor. I verified that it gets called and even the drawRect: method is called, but I don't see the contents of the nib-file on the screen. – Michael May 15 '11 at 21:44
  • In order to display a view, you must put it in a window. – Dietrich Epp May 16 '11 at 06:23
  • I know :-) But where is the view? I didn't connect the view outlet as Bavarious pointed out. But finally, I don't like to do so much work just to display a nib file, so I created my own view controller class that Just Works (tm). Just needed 70 lines of code, including empty lines and comments, to create a view controller class that is actually better than NSViewController. With MyViewController I don't need to specify the nib name and I don't need to connect the view outlet. – Michael May 16 '11 at 14:11
  • Hm, it may "Just Work" with 70 lines of code, but using a Nib file it should be more like 4 lines of code, if not less. – Dietrich Epp May 16 '11 at 17:30