繁体   English   中英

Cocoa MVC:“模型控制器”和“视图控制器”之间的交互

[英]Cocoa MVC: interaction between “model controller” and “view controller”

刚刚开始在BNR的Mac OS X Cocoa程序设计(第4版)的帮助下学习Objective-C和Cocoa,我正在研究基于文档的应用程序。 我已经阅读了Apple关于文档体系结构的开发人员文档,并选择了子类NSWindowController并覆盖我的NSDocument子类上的makeWindowControllers 我有几个理由这样做:

  • 将模型逻辑(在NSDocument子类中)与视图逻辑(在NSWindowController子类中)分开。
  • 自定义我的文档窗口的标题(Apple的开发人员文档说,没有不必要的副作用的正确方法是子类NSWindowController并覆盖windowTitleForDocumentDisplayName:
  • Apple的文档似乎强烈建议将NSWindowController子类NSWindowController除最简单的应用程序以外的所有应用程序,而我的文档肯定不是“简单”

所以,我的NSDocument子类是一个模型控制器 ,我的NSWindowController子类是一个视图控制器 此外,我理解应用程序的“工作”大部分是在控制器对象中完成的,因为视图和模型应该尽可能与应用程序无关并且可以重用。 现在我的问题是:这两种类型的控制器如何实现这种“工作”?

例如,假设我正在编写电子表格应用程序,并且我想要一个菜单​​项(或工具栏按钮),它会显示一张表,用于从我的某些数据创建图表或图表。 在该表中,用户将输入各种参数和选项以了解如何创建图表或图表,然后单击“确定”(或调用任何按钮)。

谁应该响应菜单项的操作,文档(模型控制器)或窗口控制器(视图控制器)? 实际加载和显示工作表的任务似乎与“视图相关”,所以它应该进入窗口控制器,对吗? 但是工作表的控制器需要一个模型来显示给用户( Chart对象,或ChartInputs ); 该模型在哪里创建并提供给纸张控制器? 文档是否应该通过创建ChartInputs模型对象来响应菜单项,然后将其传递给窗口控制器,窗口控制器创建图纸控制器,将模型对象传递给它,并显示工作表? 或者窗口控制器应该响应菜单项,请求新的模型对象(可能通过依赖注入通过某种工厂提供到窗口控制器的构造函数中),然后继续创建图纸控制器,传递模型,并显示表?

用户填写表单并单击“确定”后怎么办? 应该在哪里返回控制来处理用户的选择并实际创建图表 - 窗口控制器,文档或两者? 如果逻辑在用户单击“确定”之后但在表单被解除之前验证用户的输入(如果某些内容无效)?

首先,考虑NSDocument的无窗口操作。 例如,您可以创建一个实用程序应用程序,它共享您的NSDocument类,打开脚本,打印或其他操作的文档,但不显示您的主文档窗口。 想象一下,您的NSDocument类重用于该应用程序 - 并将您不想要的逻辑放入您的窗口控制器中。 这样,NSDocument子类主要负责影响文档状态的活动。

这些是模型控制器(NSDocument子类)的职责:

  • 序列化和反序列化
  • 加载和保存
  • 操纵文档的状态
  • 管理和分派打印视图
  • 监视文档以供其他人更改
  • 刷新支持数据源 - 影响文档模型的源 - 并根据需要对模型和文档应用更改
  • 管理与文档相关的活动日志
  • 拥有撤消经理
  • 将基本模型对象公开给视图控制器
  • 创建窗口控制器
  • 促进一些编辑行为,例如更改一个属性,触发创建或删除对象

如果您正在使用Core Data,则托管对象上下文,持久性存储协调器和持久性存储是模型控制器的一部分,而不是模型。 当然,托管对象本身也是模型的一部分。

这将这些责任留给了模型:

  • 用于插入,重新排列和删除模型对象的辅助方法
  • 帮助方法访问模型的特定部分
  • 数据验证
  • 以各种格式将模型渲染为字符串
  • 序列化和反序列化自己
  • 促进一些编辑行为,例如更改一个属性,触发对其他属性的更改

另一方面,这些是视图控制器的职责:

  • 操作视图以使其与模型保持同步
  • 操作视图以使其与文档状态保持同步
  • 响应本地化操作,例如添加或删除模型对象的按钮
  • 在这些视图中呈现辅助视图并响应输入
  • 调度受UI中的选择影响的操作,例如表视图中的选定行
  • 管理编辑期间使用的辅助控制器,这些辅助控制器与文档本身无关(例如Web服务数据)
  • 用作视图对象的数据源

如果您正在使用Cocoa绑定,则绑定也是视图控制器的一部分。

该设计在视图控制器和模型控制器之间产生合理的职责分离。 但是,它们位于视图和模型之间。 虽然这会产生模块化,但它不会产生去耦。

虽然我确实考虑过无窗操作,但我很大程度上是凭经验得出这种设计模式 - 将相似的代码放在一起并分离出感觉不合适的代码。 我很好奇,如果其他人发布了权威的来源或参考,这些来源或参考文献同意或不同意如何做到这一点。


举个例子,我建议这个设计:

  1. EditorWindowController创建ChartParameters对象并为其提供对文档模型的引用:

     [[ChartParameters alloc] initWithWorkbook:self.document.workbook] 
  2. EditorWindowController设置新图表视图,它可能有自己的NewChartViewController。 它将ChartParameters和文档对象传递给NewChartViewController并显示窗口。

  3. ChartParameters对象负责验证用户的选择。 NewChartViewController需要操作视图以使其与验证结果保持同步。 (避免让用户犯错误:不要等到最后验证输入。)

  4. 视图完成后,NewChartViewController会要求模型使用给定的参数创建新图表:

     [self.document.workbook addChartWithParameters:self.chartParameters] 

如果您希望not-a-chart对象成为文档的一部分,您可以这样做:

  1. EditorWindowController要求文档模型创建一个新的图表对象:

     Chart *newChart = [self.document.workbook addChart] 
  2. 新图表应设置一个标志,表示它尚未准备好显示。

  3. EditorWindowController设置NewChartViewController,将其传递给图表,显示窗口。

  4. Chart对象验证用户的选择,NewChartViewController使视图保持同步。

  5. 完成后,告诉图表它已准备好显示。 或者,如果用户取消,请将其删除。

在这些设计中的任何一个中,NewChartViewController都是一个模型控制器和视图控制器,针对其特定任务进行了本地化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM