说实话,我甚至不知道从哪里开始。我觉得我已经在圈子里跑了几个小时尝试不同的事情。
我的问题是如何在IB中配置NSWindowControllers,NSViewControllers和NSViews,然后访问层次结构中的每个,以使用单个NSWindowController切换出NSViewControllers ......
我从Apple网站开始使用此代码,并尝试更改它以适合我的情况: https://developer.apple.com/library/mac/samplecode/ViewController/Listings/MyWindowController_m.html#//apple_ref/doc/uid/DTS10004233-MyWindowController_m-DontLinkElementID_12
我有一个小应用程序,有2个视图需要根据用户交互来回切换。我们称之为drop_view和table_view。 Drop_view是在启动时加载的视图。 我的两个视图都在单独的nib文件中配置:
RADropViewController.xib
RADropViewController.m
RADropViewController.h
RADropView.m
RADropView.h
RADropViewController.xib
RADropViewController.m
RADropViewController.h
RADropView.m
RADropView.h
每个笔尖都有文件所有者,第一响应者,应用程序,视图图标和对象。 File's Owner设置为控制器类,View Icon设置为View类,Object图标设置为View Controller类。
然后我有一个带窗口控制器的窗口控制器笔尖。
RAWindowController.xib
RAWindowController.h
RAWindowController.m
nib将文件所有者设置为RAWindowController,将Window设置为NSWindow,将对象设置为RAWindowContoller。我在这个笔尖的窗口中也有一个自定义视图,因为在Apple示例中有一个NSView插座,我在所有研究中读取了stackoverflow,并且通常有一个带有主机视图的窗口控制器,它是曾经主持过不同的NSWindowControllers)。
网点是:
文件所有者
Outlets
myTargetView -> Custom View
Referencing Outlets
delegate -> Window - Window
窗口 - 窗口
Outlets
delegate -> File's Owner
Referencing Outlets
window -> Window Controller
窗口控制器
Outlets
myTargetView -> Custom View
window -> Window - Window
这是我的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
和我的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;
}
以下是我想要切换到table_view时调用的drop_view示例代码
-(void)showDifferentViewController: (NSViewController *) controller{
_windowController = [[RAWindowController alloc] initWithWindowNibName:@"RAWindowController"];
[_windowController changeViewController:1];
}
所以一切都按照我的预期发布。 drop_view被加载并且看起来都很好。 当我尝试加载table_view时,事情开始分崩离析。
这行代码:
[myTargetView addSubview:[self.myCurrentViewController view]];
是问题,至少表面上看。 myTargetView是零。它在发布时不是零,但在我尝试加载新视图时为零。因此没有加载新视图。我的drop_view只是停留在那里,因为什么也没发生。 myTargetView代表我的主机视图(据我所知)。它是我的nib文件中窗口上的自定义视图。您可以在我的RAWindowController.h文件中看到它设置的插座,该连接对我来说是好的。似乎丢失的引用可能是由于主机视图被卸载了?
我想也许这篇文章救了我: 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]];
...但我意识到我的self.window对象是nil(我假设因为我的window对象设置为 .nib中的NSWindowController。
我有一种感觉,我没有掌握关于Windows,控制器,如何配置它们以及以编程方式访问它们的非常基本的东西。 我很感激你的任何见解。
答案 0 :(得分:7)
好的,所以这就是我在问你关联的问题后的九个月里所提到的。无论何时混合和匹配笔尖,视图控制器和窗口控制器,事情都会变得毛茸茸。但是,如果你认为积极的想法,数到三,并敲木头,有时事情就会落到实处。
这就是我精神上打破各种控制器的方式:
NSWindowController (MyWindow.xib)
|
|-- NSViewController (MyFirstView.xib)
|
|-- NSView
|
|-- NSTextField
|-- NSButton
|-- NSImageView
|-- Etc.
|
|-- NSViewController (MySecondView.xib)
|
|-- NSView
|
|-- NSTableView
|-- NSButton
|-- Etc.
因此,在您的情况下,您需要在 RADropViewController.xib 中执行以下操作:
RADropViewController
是在“自定义类”字段中输入的类。RADropView
是在“自定义类”字段中输入的类。view
插座。您现在已将视图控制器连接到其视图。通过在 RADropViewController.m 中执行以下操作,可以在代码中完成同样的事情:
- (void)awakeFromNib
{
self.view = [[RADropView alloc] initWithFrame:NSMakeRect(0, 0, 250, 250)];
}
现在在 RATableViewController.xib (或 RATableViewController.m 中重复这些步骤,如果您决定使用代码路径)。
为了清楚起见,您可以在代码中连接Interface Builder 或中的视图,但不能同时连接两者。我曾经不小心覆盖了我的观点,因为我会在IB中设置它们,然后再在-awakeFromNib
方法中设置它们。回想一下,我看到我基本上重做了我在Interface Builder中所做的一切,但是直到我真正掌握了nib unarchiving过程,这似乎是合乎逻辑的事情。无论如何......回到乐趣。
现在您的视图控制器已全部设置完毕,请跳至 RAWindowController.xib 。再次,确保“文件所有者”对象指向您的窗口控制器类,并将窗口连接到window
插座。
在 RAWindowController.h 中,通过将IBOutlet
宏关键字添加到视图控制器属性来制作视图控制器插座:
@property (nonatomic, strong) IBOutlet RADropViewController *dropViewController;
@property (nonatomic, strong) IBOutlet RATableViewController *tableViewController;
现在回到 RAWindowController.xib ,将两个视图控制器对象从对象浏览器拖到侧边栏。在Identity Inspector中,将每个类设置为其各自的视图控制器类,并在Attributes Inspector中,将每个的Nib Name设置为您之前使用的nib。现在,将视图控制器对象连接到刚创建出口的属性。
最后,要切换视图,请将此类内容添加到 RAWindowController.m :
- (void)changeViewController:(NSInteger)whichViewTag
{
NSView *contentView = self.window.contentView;
switch (whichViewTag)
{
case kDropView:
{
self.myCurrentViewController = self.dropViewController;
break;
}
case kTableView:
{
self.myCurrentViewController = self.tableViewController;
break;
}
}
if ( contentView.subviews.count > 0 )
{
[contentView replaceSubview:contentView.subviews[0]
with:self.myCurrentViewController.view];
} else {
[contentView addSubview:self.myCurrentViewController.view];
}
}
我现在很累,所以我可能错过了什么。然而,我不得不发帖,看看我不久前是如何与这些东西挣扎的。我希望我能帮助一点。如果我不清楚任何事情,请告诉我,我会尝试更好地解释。不过我向你保证:最终都会有意义。有一天它只是“点击”,你会嘲笑这个旧的Stack Overflow问题。祝你好运,如果我能更清楚地了解你不确定的事情,请告诉我。放轻松。