views:

1486

answers:

1

I am developing an OS X/Cocoa application and I want behavior like this:

  • There is a sidebar with different options, let's say "Option A", "Option B", and "Option C".
  • When you click A, B, or C, it loads a corresponding GUI into the main pane. Each GUI is a different NSView subclass, and it is defined in a different NIB/XIB file. For example, Option A might 3 buttons and be an instance of NSViewSubclassA while Option B might have 1 button and a text field and be an instance of NSViewSubclassB.

How would I go about programming this?

+5  A: 

Start by subclassing NSViewController, so each of your subviews has a controller. In your action method when the user clicks a button to switch between views, you can create a new view controller with the appropriate class and nib (keep a reference to it in an ivar in the window controller). The view controller acts as the nib's owner. Then all you have to do is add the view controller's view as a subview in the main window, and you're set.

Here's a quick example. This is called in the main window controller from the action method (and after launch) after doing a few non-related tasks; the only tricky part is patching the responder chain (if you're lucky you might not need to do this).

- (void)_setAccessoryViewControllerFromTag:(NSInteger)tag;
{
    if ( _accessoryContentViewController != nil )
    {
     [self setNextResponder:[_accessoryContentViewController nextResponder]];
     [_accessoryContentViewController release];
    }

    switch ( tag )
    {
     case 0:
      _accessoryContentViewController = [[RLGraphsViewController alloc] initWithNibName:@"GraphsView" bundle:nil];
      break;
     case 1:
      _accessoryContentViewController = [[RLSummaryViewController alloc] initWithNibName:@"SummaryView" bundle:nil];
      break;
     case 2:
      _accessoryContentViewController = [[RLEquipmentViewController alloc] initWithNibName:@"EquipmentView" bundle:nil];
      break;
     default:
      _accessoryContentViewController = [[RLLocationsViewController alloc] initWithNibName:@"LocationsView" bundle:nil];
      break;
    }

    [_accessoryContentViewController setNextResponder:[self nextResponder]];
    [self setNextResponder:_accessoryContentViewController];     
    [self.accessoryView setContentView:[_accessoryContentViewController view]];
}
Marc Charbonneau
You shouldn't use a single leading underscore to start your ivar or method names. That's an internal Apple coding convention, which they adopted to avoid the hazard of name collision with outside developers' code.
NSResponder