NSWindowController澄清理解

我已经多次在项目中使用NSWindowController,并且觉得我对这个重要的类背后的概念有非常粗略的把握。 我想用这个post来做的是澄清/纠正我自己的理解,并希望帮助其他学习者进入理解的第一步。 我发现这些概念,概述和最佳实践是最有用的,而且往往缺less文档。 这里是我对NSWindowController的看法(问题穿插在粗体中):

  • 一个NSWindowController(NSWC)子类存在于(概念上)每个窗口笔尖之下,充当用户界面元素和它们控制/表示的模型对象之间的粘合剂。 基本上,应用程序中的每个窗口都应该有自己的NSWC子类。
  • 笔尖的文件所有者应始终是NSWC子类。 这甚至是MainMenu.xib应用程序的情况吗?
  • NSWC window属性应始终链接到InterfaceBuilder中的NSWindow。
  • 你应该使用[super initWithWindowNibName:]重写'init'方法,这样当你引用[mycontroller window] ,它将加载nib。 对于MainMenu.xib窗口,NSWC是否也应该这样做,即使这是在启动时打开的?
  • NSWC不应该做太多的繁重工作 – 它只是简单地将消息传递给对象的实例,并将这些对象呈现在UI中。
  • 它可以使用绑定来修改用户界面,或者作为表格的委托来进行修改,或者当它观察到一个变化时主动地改变用户界面元素,或者是上述任何一个组合(你使用哪一个似乎是一个问题)口味,各方面都有利有弊)。
  • NSWC可以在必要时创build其他NSWC的实例(例如,打开一次性子窗口时)。
  • 使用[mycontroller showWindow:nil]在前面显示相关的窗口。 如果您希望窗口显示为表单,请使用如下所示的内容:

     NSWindowController* mycontroller = [[MyController alloc] init]; [NSApp beginSheet: [mycontroller window] modalForWindow: [self window] modalDelegate: self didEndSelector: @selector(didEndMySheet:returnCode:contextInfo:) contextInfo: nil]; 

didEndSelector:应该是父窗口的NSWC的一个方法,并且可以通过[sheet windowController] windowController [sheet windowController]访问和释放'mycontroller'。 – closures窗口调用NSWC窗口的performClose:方法。

一些问题:

  • MainMenu窗口的NSWC是否也是应用程序代表,还是应该是不同的类?
  • 同样,NSWC主要处理文件(拖放和打开),还是应该传递给应用程序代表,还是仅仅是一个品味问题?

如果这是不好的做法,请纠正我,或者是错误的。 我期待澄清我对NSWindowController的理解,所以任何补充(以最佳实践,经验,陷阱的forms)将不胜感激。

谢谢,劳里

什么是窗口控制器实际上?

窗口控制器是从NIB文件加载窗口和pipe理在NIB中分配的资源的内存的工具。 在此之前, NSWindowControllers基本上必须为每个窗口编写相同的代码,或者创build一个自己的窗口控制器类。

当然,它们也是Model / View / Controller意义上的控制器,所以它们是将视图从窗口连接到模型对象的正确位置。 为此,他们经常需要充当视图对象的委托或数据源。 所以你得到这个部分是完全正确的。

窗口控制器也是代码重用的工具。 它可以很容易地将窗口控制器类和它的XIB / NIB放到另一个项目中并在那里使用。

所以是的,NIB的每一个窗口都应该由一个窗口控制器拥有,只有一个例外。 实际上,这只是良好的代码指南,没有什么强制执行它。

WindowControllers和MainMenu.xib

MainMenu.xib是一个不同的东西,那里你不能使用窗口控制器。 这个NIB被NSApplication加载,所以它必须是“Files owner”。 在NSApplication和NIB之间没有办法获得窗口控制器。 这里也没有必要使用窗口控制器来进行内存pipe理,因为应用程序对象是为程序的整个运行时间而存在的,所以当它被取消分配时,不需要从NIB清除它的资源。

如果你真的需要一个主窗口的窗口控制器,你不能把它放在MainMenu.xib

我希望这有帮助。 窗口控制器可能还有很多要说的

这甚至是MainMenu.xib应用程序的情况吗?

不,MainMenu nib由NSApplication(这是谁加载它)拥有。

对于MainMenu.xib窗口,NSWC是否也应该这样做,即使这是在启动时打开的?

不,NSApplication根据您的应用程序文件的“NSMainNibFile”属性加载主要的笔尖。 (它只是在模板Xcode项目中预先设置为“MainMenu”)。如果你想改变它的名字然后在那里改变它(并且重命名你的nib文件)。 (顺便说一下,这个属性也可以在Xcode 4中的目标的“摘要”视图中进行更改。)

MainMenu窗口的NSWC是否也是应用程序代表,还是应该是不同的类?

NSMainNibFile nib的所有者是加载它的NSApplication的实例,并通过关联该实例的任何代理。 这些都不是NSWC的子类。

同样,NSWC主要处理文件(拖放和打开),还是应该传递给应用程序代表,还是仅仅是一个品味问题?

没有“主要的NSWC”(app / app-delegate是NSMainNibFile的控制器)。

所有拖放操作都由NSWindow或NSView子类处理。 我通常使用一个特殊的NSWindow或NSView的子类,只是通过所有的拖放方法,直到代表。 例如:

 - (unsigned int) draggingEntered:sender { return [[self delegate] draggingEntered:sender]; } 

这样我就可以将我所有的窗口/视图代码放在各自的控制器中(由它们的笔尖所有者决定)。 而且由于窗口/视图特定的代码在控制器(而不是NSWindow / NSView子类)中,所以不同types的NSWindows / NSView都可以使用相同的拖放子类。