Jake Foram
Jake Foram

Reputation: 21

Subclass NSViewController or NSView

I need to have a view which will contain controls like sliders and buttons, and have a colored background. I am unsure whether to subclass NSView or NSViewController. I thought I could subclass an NSView and draw a custom background and layout the controls in a xib, and set the outlets to the NSView subclass.

Some buttons need to toggle, eg a Play/Pause button, I thought this logic should be done in the NSView, and NSViewController be notified when the button toggles, rather than the NSViewController having to manage the toggle it self.

But when I go to create a NSView subclass the option to create a xib is greyed out, it is only possible with an NSViewController. So do I have to have the outlets on the NSViewController?

I wanted myView.playPauseButton, but it seems I have to have myViewController.playPauseButton?

Upvotes: 2

Views: 2354

Answers (2)

sergio
sergio

Reputation: 69037

I need to have a view which will contain controls like sliders and buttons, and have a colored background. I am unsure whether to subclass NSView or NSViewController. I thought I could subclass an NSView and draw a custom background and layout the controls in a xib, and set the outlets to the NSView subclass.

If you want to use a xib, you have to go with a NSViewController subclass; that's what it is for, among other things.

In general, for what you are trying to do (bundling several controls together), NSViewController is the class to use.

You can also see this from the point of view of the Model-View-Controller pattern (that is where view controllers and views come from): the view has to do with how things appear; the controller has to do with user interaction (and interaction with the model).

You could certainly define a NSView subclass and define its content, either programmatically or in IB (adding the slider and the buttons as subviews to it), but I don't see much advantage to it, unless you are going to provide a kind of specific control.

EDIT:

You state in a comment that you would like use use your custom, IB-defined NSView inside of a NSSplitView. This makes things a bit more contextualized.

Now, as usual there are many design options, e.g., you might define your own MySplitController allowing you to specify the nibs from which the split view's subviews should be loaded.

But, if I understand your aim correctly, what you would like to do is defining an NSView in a xib and have it used within an NSSplitView, like if it were one of the default views types that IB allows.

This was allowed by Interface Builder Plug-ins. Unfortunately, they seem to be not supported anymore in Xcode 4.

Then the only option I see is to define a subclass of NSView, e.g., MyCustomView and then in its initWithFrame: method load the xib file, identify the view you defined in it, and adding it as a subview.

Specifically, you can use this code to load the xib files top level objects, among which your custom view will be found:

NSNib *nib = [[[NSNib alloc] initWithNibNamed:@"MyView" bundle:nil] autorelease];
NSArray *topLevelObjects;
if (![nib instantiateWithOwner:customViewOwner topLevelObjects:&topLevelObjects]) {
    //- handle error
}

MyView *myView = nil;
for (id topLevelObject in topLevelObjects) {
  if ([topLevelObject isKindOfClass:[MyView class]) {
    myView = topLevelObject;
    break;
  }
}

To simplify things, you can have this xib file only define your custom NSView and the ubiquitous File's Owner (which is the link to integrating the view into the rest of your app).

As you see, I am passing a customViewOwner to instantiateWithOwner: this would be your main view controller or app delegate in charge for responding to all actions coming from the custom view and to set its state when required. This class would be the file owner of your xib, so to have a really modular design, it would be better to define your MyCustomViewController that you subclass in specific projects.

Once you have defined such a custom NSView subclass, then the only thing you need to do to integrate it into your NSSplitView is setting the NSSplitView's subviews Class to MyCustomView.

This is not as straightforward as using an IB plug-in, but it can serve well the purpose of integrating views defined in different xib files.

Upvotes: 3

Kyle
Kyle

Reputation: 434

Its best to subclass NSViewController and init with a xib or layout your subviews manually in code. From my experience, subclassing NSView has never worked out the way I've wanted it too, including the implementation you're looking for.

Upvotes: -1

Related Questions