To be honest, I don't even know where to start. I feel like I've been going around in circles for hours trying different things.
My issues are around how to configure NSWindowControllers, NSViewControllers, and NSViews in IB and then access each in a hierarchy to switch out the NSViewControllers using a single NSWindowController...
I started with this code from the Apple site and am trying to alter it to fit my situation: https://developer.apple.com/library/mac/samplecode/ViewController/Listings/MyWindowController_m.html#//apple_ref/doc/uid/DTS10004233-MyWindowController_m-DontLinkElementID_12
I have a small app that has 2 views that need to be switched back and forth depending on user interaction. Let's call them drop_view and table_view. Drop_view is the view that is loaded on launch. Both of my views are configured in separate nib files:
RADropViewController.xib
RADropViewController.m
RADropViewController.h
RADropView.m
RADropView.h
RADropViewController.xib
RADropViewController.m
RADropViewController.h
RADropView.m
RADropView.h
Each nib has a File's Owner, First Responder, Application, View Icon, and Object. The File's Owner is set to the controller class, the View Icon is set to the View class, and the Object icon is set to the View Controller class.
Then I have a window controller nib with a window controller.
RAWindowController.xib
RAWindowController.h
RAWindowController.m
The nib has File Owner set to RAWindowController, Window set to NSWindow, and an Object set to RAWindowContoller. I also have a Custom View in the window in this nib because there is an NSView outlet in the Apple example and I read on stackoverflow in all of my research that "there is usually a window controller with a host view and which is used to host the different NSWindowControllers).
The outlets are:
File's Owner
Outlets
myTargetView -> Custom View
Referencing Outlets
delegate -> Window - Window
Window - Window
Outlets
delegate -> File's Owner
Referencing Outlets
window -> Window Controller
Window Controller
Outlets
myTargetView -> Custom View
window -> Window - Window
Here is my RAWindowcontroller.h
@class RADropViewController, RATableViewController, RAWindowView;
@interface RAWindowController : NSWindowController
{
IBOutlet NSView *myTargetView;
}
@property (nonatomic, assign) NSViewController *myCurrentViewController;
@property (nonatomic, strong) RADropViewController *dropViewController;
@property (nonatomic, strong) RATableViewController *tableViewController;
-(void)changeViewController:(NSInteger)whichViewTag;
- (NSViewController *)viewController;
@property (strong) IBOutlet NSView *myTargetView;
@end
and my RAWindowController.m
#import "RAWindowController.h"
#import "RADropViewController.h"
#import "RATableViewController.h"
@interface RAWindowController ()
@end
@implementation RAWindowController
@synthesize myCurrentViewController, myTargetView;
enum // popup tag choices
{
kDropView = 0,
kTableView,
};
NSString *const kDropViewTitle = @"RADropViewController";
NSString *const kTableViewTitle = @"RATableViewController";
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
}
return self;
}
-(void)awakeFromNib{
_dropViewController = [[RADropViewController alloc] initWithNibName:kDropViewTitle bundle:nil];
_tableViewController = [[RATableViewController alloc] initWithNibName:kTableViewTitle bundle:nil];
[self changeViewController:kDropView];
[myTargetView addSubview:[self.myCurrentViewController view]];
[self.window center];
[self.window setContentMaxSize:NSMakeSize(409.0, 295.0)];
[self.window setContentMinSize:NSMakeSize(409.0, 295.0)];
}
-(void)windowWillLoad{
[super windowWillLoad];
}
- (void)changeViewController:(NSInteger)whichViewTag
{
if ([self.myCurrentViewController view] != nil)
{
[[self.myCurrentViewController view] removeFromSuperview];
}
switch (whichViewTag)
{
case kDropView:
{
if (self.dropViewController == nil)
{
_dropViewController = [[RADropViewController alloc] initWithNibName:kDropViewTitle bundle:nil];
}
myCurrentViewController = self.dropViewController;
break;
}
case kTableView:
{
if (self.tableViewController == nil)
{
_tableViewController = [[RATableViewController alloc] initWithNibName:kTableViewTitle bundle:nil];
}
myCurrentViewController = self.tableViewController;
break;
}
}
[myTargetView addSubview:[self.myCurrentViewController view]];
}
- (NSViewController *)viewController
{
return self.myCurrentViewController;
}
Here is some sample code from my drop_view that I call when I want to switch to my table_view
-(void)showDifferentViewController: (NSViewController *) controller{
_windowController = [[RAWindowController alloc] initWithWindowNibName:@"RAWindowController"];
[_windowController changeViewController:1];
}
So everything works as I would expect on launch. The drop_view gets loaded and all looks good. Things start to fall apart when I try to load the table_view.
This line of code:
[myTargetView addSubview:[self.myCurrentViewController view]];
is the issue, at least on the surface. myTargetView is nil. It's not nil on launch but is nil when I try to load a new view. So no new view gets loaded. My drop_view just stays there as nothing happened. myTargetView represents my host view (as I understand it). It's the custom view on my window in my nib file. You can see the outlet to it set up in my RAWindowController.h file and that connection looks OK to me. It seems like the reference is being lost maybe due to the host view being unloaded?
I thought maybe this post had saved me: How exactly does an NSView, an NSViewController, and MainMenu.xib fit together?
[self.window.contentView addSubview:self.customViewController.view];
[self.customViewController.view setFrame:[self.window.contentView bounds]];
...but I realized my self.window object is nil (I'm assuming because my window object is set to an NSWindowController in the .nib).
I have a feeling I'm failing to grasp something very basic about windows, controllers, how to configure them, and to access them programmatically. I appreciate any insight you have.