例如,我有窗口(非文档模型) - 它有一个与之关联的控制器。在此窗口中,我有一个列表和一个添加按钮。单击添加按钮将显示另一个“详细信息”窗口/对话框(带有关联的控制器),允许用户输入详细信息,单击确定,然后将项目传播回原始窗口名单。显然,我会有一个基础模型对象,它包含这些实体的集合(让我们将单个实体称为实体以供参考)。
可以想象,我只有一个主窗口,所以我可能只有一个实体集合。我可以将它藏在主窗口的控制器中 - 但是如何将它传递给细节窗口?我的意思是,我可能不希望传递这个集合 - 难以阅读/维护/多线程。我可以传递一个对父控制器的引用并使用它来访问集合,但这似乎也闻起来。我可以将它存储在appDelegate中,然后通过[[NSApplication sharedApplication]委托]将其作为“全局”变量访问 - 这似乎有点过分,考虑到应用委托与模型没有任何关系。另一个全局变量样式可能是一个选项 - 我可以使Entity类具有用于集合的单例工厂和用于访问集合的类方法。这似乎比appDelegate更大的滥用 - 特别是考虑到Entity对象和所述实体的集合是两个独立的问题。我可以创建一个EntityCollection类,它具有单例工厂方法,然后是对象与集合交互的方法(或者分成真正的工厂类和集合类,以获得更多的OO优点并轻松替换测试对象)。如果我使用的是NSDocument模型,我想我可以将它存放在那里,但这与在应用程序委托中存储它没有太大的不同(尽管NSDocument本身看起来似乎以某种方式表示模型)。
我最近花了很多时间在服务器端,所以我没有必要对付客户端很多,当我有,我只是暴力迫使解决方案。最后,有十亿种方法可以为这只猫提供皮肤,看起来它们都不是非常干净或漂亮。普遍接受的Cocoa程序员的做法是什么?或者,更好的是,这样做的最佳方式是什么?
答案 0 :(得分:7)
我认为你的概念问题在于你正在考虑将接口作为应用程序的核心,将数据模型视为必须找到一个地方来填充某个地方的东西。
这是倒退的。数据模型是程序的核心,其他所有内容都被移植到数据模型中。该模型应该封装可以对数据执行的所有逻辑操作。接口,GUI或其他方式,仅向请求某些操作的数据模型发送消息。
从这个概念开始,很容易看出普遍可访问的数据模型不是草率设计。由于模型包含用于更改数据的所有逻辑,因此您可以使用任意大量的接口来访问数据,而不会使数据变得混乱或代码复杂,因为模型仅根据其自己的内部规则更改数据。
完成通用访问的最佳方法是创建一个单例生成类,然后将该类的标头放在应用程序前缀头中。这样,应用程序中的任何对象都可以访问数据模型。
Edit01:
让我澄清裸全局变量和全局可访问类封装数据模型之间的重要区别。
从历史上看,我们将全局变量视为糟糕的设计,因为它们只是原始变量。代码的任何部分都可以随意改变它们。这种裸露导致了明显的问题,你必须不断防止一些代码的流浪片段改变全局,然后降低应用程序。
但是,在基于类的全局变量中,全局变量由封装类实现的逻辑封装和保护。这种封装意味着虽然代码的任何杂散片段都可能尝试改变类中的全局变量,但只有封装类允许更改时才能这样做。自动验证降低了代码的复杂性,因为所有验证逻辑都驻留在一个单独的类中,而不是在数据可能被操纵的任何随机位置遍布应用程序。
您可以创建强大且通用的数据验证和管理,而不是像裸全局变量那样创建弱点。如果您发现数据管理存在问题,则只需将其修复到一个位置即可。一旦你有一个正确配置的数据模型,应用程序的其余部分变得非常容易编写。
答案 1 :(得分:2)
我最初的反应是使用“模态委托”,就像NSAlert
一样。您可以通过传递对委托的引用来创建详细信息窗口,详细信息窗口在创建对象时会向其发送消息。委托 - 可能是主窗口的控制器 - 然后可以处理“完成编辑”消息并将对象添加到集合中。我倾向于不想直接传递这个集合。
答案 2 :(得分:0)
我支持EntityCollection类。如果你有一个对象列表,我认为该列表应该在特定控制器之外进行管理。
答案 3 :(得分:0)
我使用单例方法,类本身管理它自己的集合,设置和拆卸。我发现这将数据库/存储功能与控制器分开并保持干净。只需调用[Object objects]
并让它返回对我的对象列表的引用,这很好而且很容易。