3

这可能是一个愚蠢的问题,但在 MVC 中,视图并不知道模型是否正确。我查看了一些表格视图单元格的示例,表格视图单元格具有模型对象的属性。然后它使用该模型的属性来填充标签或单元格的图像。

或者在另一种情况下,如果我有一个 UIView 可以根据模型动态绘制某些东西,那么在 UIView 上拥有一个属性似乎是最简单的,这样 UIView 可以访问该模型的数据以动态绘制它。所以我可以做这样的事情:

myView.object = newObject;
[myView setNeedsDisplay];

这对 MVC 来说是错误的吗?如果是这样,做这两件事的更好方法是什么?谢谢。

4

3 回答 3

4

MVC 模型有不同的变体——关于 Cocoa 的 Apple 文档在这里:http: //developer.apple.com/library/mac/documentation/General/Conceptual/CocoaEncyclopedia/Model-View-Controller/Model-View -Controller.html#//apple_ref/doc/uid/TP40010810-CH14-SW9

我从中得到的主要内容是视图不应该直接链接到模型。看这张图:

Cocoa MVC 模式的苹果图

您经常提到UITableViewCells具有Model对象的属性-我认为这是错误的。模式应如下所示:

  • 模型处理所有实际的数据存储和管理
  • View知道正在显示的数据类型,但不知道数据本身
  • 控制器(UITableViewController)是从模型中获取数据并设置视图的“粘合剂”

这在实践中如何运作?

请原谅以下伪代码中的一些错误,因为我只是直接输入了它,我没有测试过它,但希望它说明了这一点。

所以你有一个UITableViewCell看起来像这样的子类:

@interface PhoneEntryTableViewCell {

@property (weak) IBOutlet UILabel *personName;
@property (weak) IBOutlet UILabel *phoneNumber;

}

模型如下所示:

@interface PhoneModel {

@property (strong) NSMutableArray *listOfPeople;

}

UITableViewController实现标准UITableViewDelegate/UITableViewDataSource方法,例如:

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  Person *person = [myModel personForIndex:indexPath.row];

  PhoneEntryTableViewCell *cell = [self dequeueReusableCellWithIdentifier:@"PhoneCell"];
  cell.personName.text = [person name];
  cell.phoneNumber.text = [person phoneNumber];

  return cell;
}

所以总而言之,视图对实际数据没有任何想法——它只知道它必须显示一个人的姓名和电话号码。它不知道后端存储是什么——它可能是核心数据、文件、下载和解析的 JSON 等。它对模型一无所知——例如,它可能存储关于模型的其他数据人,也许电话号码实际上存储在与名称不同的模型中。控制器处理所有这些工作。

为什么要这样做?

因此,您推出上述应用程序,然后发现您的模型非常慢 - 您可以将其换成完全不同的模型,而无需接触View。也许您可以让其他开发人员或设计师创建视图- 他们只需要知道它必须显示两位文本。基本上,它允许您的代码干净、清晰分区、易于扩展且更易于重构。

现在,只要您在UITableViewCell视图中执行此类操作,所有这些都会消失:

@property (strong) Person *person;
于 2012-07-26T19:41:54.783 回答
0

首先:没有“MVC 模型”。它以不同的方式用微妙的方式概述,但重要的区别。

如果视图中的组件需要获取信息,它可以通过两种方式获取信息:请求(轮询)或被通知(推送)。在大多数情况下,通知应该是更简洁的方法,因为视图实际上对模型一无所知,它只是作为观察者工作。

但是,GUI 组件往往需要“模型对象”来保存数据并且可以被要求提供数据,就像在您的示例中一样。尽管它们通常以模型命名,但在架构上它们不需要属于它。在我看来,他们不应该这样做,因为模型的界面是在预定义的 GUI 组件的需求之后构建的,而 MVC 的整个意义就消失了。如果你想要模型和视图之间的清晰分离,你应该尝试这样的事情:

-----------------       -----------------       --------------      ---------
| GUI Component | --->  | "Model Class" | <-->  | Controller | ---> | Model |
-----------------       -----------------       --------------      ---------

因此,GUI 组件所期望的“模型类”对象只不过是控制器的适配器。在 GUI 和控制器之间的这种关系中,您现在可以实现您喜欢的任何策略 - 轮询或推送(双向箭头的原因)。

于 2012-07-26T18:55:06.853 回答
0

或者在另一种情况下,如果我有一个 UIView 可以根据模型动态绘制某些东西,那么在 UIView 上拥有一个属性似乎是最简单的,这样 UIView 可以访问该模型的数据以动态绘制它。

那么,为了获得正确的信息,您想让视图对模型说些什么呢?它必须对模型有所了解才能提出正确的问题,对吧?或者,您可以定义一个类似的协议UITableViewDataSource并发送类似的通用消息-cellForRowAtIndexPath:,然后在您的模型中实现该协议。这避免了视图需要知道关于模型的任何特定信息,但这意味着模型现在必须知道视图——它必须知道视图中应该显示的内容,以便它可以通过返回正确的数据。无论您采用哪种方式,都会在模型和视图之间引入依赖关系,这意味着当您对其中一个进行更改时,您将不得不对另一个进行更改。

避免这些依赖正是 MVC 架构的重点。控制器知道模型和视图,这允许模型和视图彼此独立存在。

有时拥有一些模型和视图都知道的对象可能是有意义的。如果您正在编写通讯簿,那么拥有一个知道如何显示联系人的 ContactView 和一个存储联系人对象的模型可能是有意义的。这似乎比拥有一个完全愚蠢的视图更明智,它可以让你传递联系人对象,而不是很长的姓名、地址、电话、传真、电子邮件等列表。你可以说联系人是一个模型对象,以上所有内容都适用:您将在 ContactView 和 Contact 之间引入依赖关系。但通常当我们谈论“模型”时,我们指的是程序用来存储数据的整个对象图,

于 2012-07-26T20:17:39.387 回答