我创建了一个 NSWindow xib 文件,我想通过单击另一个窗口中的按钮来打开该文件。
现在,为了控制 NSWindow 的行为,我从 xib 中的库中拖动了一个对象,并将其更改为我在 XCode 中定义的 NSWindowController(即 ListingWindowController)的子类。
类似地,我还创建了 NSViewController 的子类(即 ListingViewController)来管理 NSWindow 内的 NSView。为此,我将 NSViewController 从 xib 的 Library 中拖出,并将其类更改为 ListingViewController。
@class ListingViewController;
@interface ListingWindowController : NSWindowController {
IBOutlet ListingViewController *listingVC;
}
@property (nonatomic, retain) IBOutlet ListingViewController *listingVC;
@end
我在IB中连接了窗口和我的窗口 Controller 的listingVC。
现在,要在启动(第一个)窗口中单击按钮来调用此窗口,我使用 initWithWindowNibName 创建窗口 Controller ,如下所示。
- (IBAction) pushConnect:(id)sender {
NSLog(@"Connect pushed.");
if (wc == nil) {
wc = [[ListingWindowController alloc] initWithWindowNibName:@"ListingWindow" owner:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeWindow:) name:NSWindowWillCloseNotification object:nil];
[wc showWindow:sender];
}
}
问题是,尽管在 IB 中为即将到来的窗口/ View 的 View Controller 完成了所有绑定(bind),但即使新窗口已加载(下面的代码)。
- (void)windowDidLoad {
[super windowDidLoad];
NSLog(@"windowDidLoad = %@, %@", self.window, self.listingVC);
}
请帮忙解释为什么连接不起作用。我已经为这个问题绞尽脑汁有一段时间了。
PS:我有 iOS 编程背景。因此,我假设 Mac 的窗口/ View Controller 的行为与 iOS UIViewController 类似。
TIA..
最佳答案
请注意:
wc = [[ListingWindowController alloc] initWithWindowNibName:@"ListingWindow" owner:self];
意味着self
(从你的问题中不清楚self
是什么)是ListingWindow.nib
的所有者。这意味着 self 是保留该 nib 文件中对象的导出的人,而 self 负责释放 nib 文件中的顶级对象。这也意味着您将在代码中创建 ListingWindowController
实例,并在 nib 文件中创建另一个实例,因为您已拖动 ListingWindowController< 类的对象
到 nib 文件上。
事情不应该是这样的。
在绝大多数情况下,窗口( View ) Controller 加载 nib 文件并成为其所有者。它有一个 window
(view
) 导出,必须链接到 nib 文件中的顶级窗口( View )。作为 nib 文件的所有者,它必须在加载 nib 文件之前创建。
为了为您的窗口 Controller 实现此目的,您需要将文件的所有者类设置为 ListingWindowController
。您不得拖动对象立方体并在 nib 文件内实例化窗口 Controller 。窗口 Controller 是nib文件的所有者,因此它必须在nib文件加载之前存在。您还必须将文件所有者中的 window
导出链接到 nib 文件中的顶级窗口对象,以便窗口 Controller 知道它应该管理哪个窗口。
完成后,使用:
wc = [[ListingWindowController alloc] initWithWindowNibName:@"ListingWindow"];
而不是:
wc = [[ListingWindowController alloc] initWithWindowNibName:@"ListingWindow" owner:self];
因为 wc
应该是 nib 文件的所有者。
View Controller 的工作原理类似。它们是在加载 nib 文件之前创建的,负责加载包含 View 作为顶级对象的 nib 文件,是该 nib 文件的所有者,并且具有必须链接的 view
导出到该顶级 View 。
从你的问题中不清楚你是否有一个单独的 nib 文件用于 View 。如果不这样做,那么根本不需要使用 NSViewController
的子类 - 您可以使用 NSObject
的子类来代替。如果您坚持使用 NSViewController 来管理不是从单独的 nib 文件加载的 View ,那么您应该重写 -loadView ,以便某些人获得对该 View 的引用意味着除了从 nib 文件加载它并发送 -setView:
以便它知道它应该管理的 View 之外。
推荐阅读:Nib Files in the Resource Programming Guide , NSWindowController class reference , NSViewController class reference .
关于cocoa - 界面生成器中的 NSWindowController 对象链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6170345/