2012-07-26 115 views
3

这可能是一个愚蠢的问题,但在MVC中,视图并不知道模型的权利。我已经看过表格视图单元格的一些示例,并且表格视图单元格具有模型对象的属性。然后使用该模型的属性来填充标签或单元格的图像。或者在另一种情况下,如果我有一个UIView根据模型动态绘制某些东西,看起来像在UIView上拥有一个属性最简单,所以UIView可以访问该模型的数据以绘制它动态地。所以我可以做这样的事情:MVC,了解模型的意见

myView.object = newObject; 
[myView setNeedsDisplay]; 

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

回答

0

或者在其他情况下,如果我有一个UIView动态画点什么 基于在模型上,似乎在UIView上拥有 属性是最容易的,因此UIView可以访问 中的模型数据以便动态绘制它。

那么,为了获得正确的信息,你对模型有什么看法?为了提出正确的问题,它必须了解模型的一些内容,对吧?或者,您可以定义像UITableViewDataSource这样的协议并发送类似-cellForRowAtIndexPath:的通用消息,然后在您的模型中实现该协议。这避免了视图需要知道关于模型的任何具体内容,但它意味着模型现在必须了解视图 - 它必须知道视图中应显示的内容,以便它可以通过取回正确的数据。无论你走到哪里,你都会引入模型和视图之间的依赖关系,这意味着当你对其中一个进行修改时,你必须对另一个进行修改。

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

让模型和视图都知道一些对象有时候可能是有意义的。如果您正在编写通讯簿,那么让知道如何显示联系人的联系人视图以及存储联系人对象的模型可能是有意义的。这似乎比拥有一个完全愚蠢的视图更明智,它可以让你传递联系人对象而不是很长的名单,地址,电话,传真,电子邮件等名单。你可以说联系人是一个模型对象,以上所有情况都适用:您将在ContactView和Contact之间引入依赖关系。但通常当我们谈论“模型”时,我们指的是程序用来存储其数据的整个对象图,MVC的好处是将您管理所有对象的方式与呈现数据的方式分开他们包含。

0

首先:没有“MVC模型”。用不同的方式概括了它们的差别,但重要的区别。

如果视图中的某个组件需要获取信息,它可以通过两种方式获取:请求它(轮询)或通知它(推送)。在大多数情况下,通知应该是更清洁的方法,因为该视图实际上不知道模型的任何内容,它只是作为observer运行。

但是,GUI组件倾向于需要“模型对象”来存放数据并且可以请求它,就像在你的例子中一样。尽管它们通常以模型命名,但在体系结构上它们不需要属于它。在我看来,他们不应该这样做,因为模型的接口是在预定义GUI组件的需求之后构建的,并且MVC的整体意义消失了。如果你想模型之间的明确分工,并查看你应该尝试这样的事:

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

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

4

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

我从中获取的主要内容是:视图不应与模型直接相关。看到这个图:

Apple diagram of Cocoa MVC pattern

你提到UITableViewCells经常具有模式对象的属性 - 我建议这是错误的。这个模式应该如下:

  • 模式处理所有实际的数据存储和管理的
  • 查看知道数据的类型正在显示,而不是数据本身。
  • 控制器(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等。它不知道任何关于模型 - 例如,它可能存储其他数据关于该人,也许电话号码实际上存储在与名称不同的模型中。 控制器可以处理所有这些工作。

为什么这样呢?

所以你推出上述应用程序,然后发现你的型号是可怕的慢的 - 你可以将其交换出去完全不同的模型,而不会触及查看。也许你可以让其他开发人员或设计人员创建查看 - 他们需要知道的一点是它必须显示两位文本。基本上它允许你的代码干净,分区清晰,易于扩展,并且更容易重构。

现在,只要你做这样的事情在你的UITableViewCell查看,这一切都消失了:

@property (strong) Person *person;