I have a NSWindowController which contains the root view. The root view has 4 NSButtons, some text and images. Each button is bound to a NSViewController. When I click on one of the buttons, the root view is removed and the view bound to the NSViewController (let’s call it the subview) is displayed. In the subview, there is a NSButton which sends a notification to the window controller to restore the root view. Here is my code (I removed most of useless part)
-
WindowController.h
@interface MainWindowController : NSWindowController { IBOutlet NSView* myTargetView; // bound to the whole view of the window NSView* viewRoot; NSViewController* myCurrentViewController; } - (IBAction)buttonClicked:(id)sender; // Not shown in the implementation - (void)changeViewController:(NSInteger)buttonTag; - (void)restoreRootView; @end -
WindowController.m
- initWithPath:(NSString *)newPath { return [super initWithWindowNibName:@"MainWindow"]; } - (void)windowDidLoad { vwRoot = [[[[self window] contentView] subviews] objectAtIndex:0]; // set up notification observer, will call restoreRootView when receiving notification from NSViewController object } - (void)changeViewController:(NSInteger)buttonTag { [vwRoot retain]; [vwRoot removeFromSuperview]; if (myCurrentViewController != nil) [myCurrentViewController release]; switch (buttonTag) { case kView1: { View1Controller * viewOneController = [[View1Controller alloc] initWithNibName:kViewOneTile bundle:nil]; if (viewOneController != nil) { myCurrentViewController = viewOneController; } break; } case kView2: { // and so on... } } [myTargetView addSubview: [myCurrentViewController view]]; [[myCurrentViewController view] setFrame: [myTargetView bounds]]; } - (void)restoreRootView { [[myCurrentViewController view] removeFromSuperview]; [myTargetView addSubview:vwRoot]; [[vwRoot setFrame:[myTargetView bounds]]; }
Unfortunately, when restoreRootView is called, the NSViewController‘s view is removed, but the root view is not displayed.
I’ve recreated your code assuming that
vwRootis the same as theviewRootdeclared in WindowController.h, and everything is correctly bound and non-nil; I’ve used a Text View as the target view, two buttons, and retained its reference while it’s replaced by another view (owned by a controller).I encountered the same problem but only with autolayout. When I disabled autolayout the code started working perfectly.
The problem was in the constraints: when the
vwRootis removed, the constraints that define its position inmyTargetVieware removed. You must define them again, otherwise your view will be placed somewhere outside the visible area (in my case, with the top left corner on the bottom left corner of the window: so, nothing visible).The code for adding the constraints (setting the frame is unnecessary):
The same should apply to
- (void)changeViewController:(NSInteger)buttonTag: when you addmyCurrentViewController.view, there shouldn’t be any constraint in place, so unless you have some code to fix that, when you resize your window your content view shouldn’t follow.