Something about MVC

MVC的主要宗旨是把所有的对象分为三个阵营,model阵营、view阵营和controller阵营
那么这些阵营都是干什么的?

一、model阵营是你的应用是做什么的

Model = What your application is (but not how it is displayed)

举个例子:你在做一个人的模型,这个人的身高,体重,性别 就是 model,这些都是“这个程序是什么”的一部分,这就是model。我并没有说关于这个人的相貌、衣着,这些和model没有关系,那是view和controller干的事。

二、controller:你可以认为是你的model如何展现在用户面前

Controller = How your Model is presented to the user (UI logic)

它获取了这个人的身高等并将这些计算出怎么在屏幕上展现出来。这就是controller,controller 控制如何在UI上展现model。

三、view 是 controller 的仆人,view 就是controller使用的工具

View = Your Controller’s minions

我们尽可能的使view阵营里的对象通用化,就像按钮、滑动条,这些都是苹果自带的。

view绝对不包含任何有关于如何去表现应用。

controller 利用这些通用view来做model需要做的事情。

view应该是很通用的,这很重要。因为系统上有很多view,还有和应用相关的功能来控制view,所以我们要更先进一点,利用通用的view来理解和使用这些功能。

四、一旦你有了三个阵营,剩下的就是他们之间的管理和通信问题

接下来我要谈一下哪些通信是被允许的,还有如何去完成

1.让我们聊一下controller是怎样向model发消息的:

controller向model发消息是100%被允许的(Controllers can always talk directly to their Model)

controller可以问model任何问题,controller知道model的任何事情
因为controller就是用来把model展现在屏幕上的,所以他要有完全的访问权

这个箭头是单向的,所以只有controller知道model

这里画的像一个交通标志,从controller到model是白色虚线,所以可以随时跨过去

2.那么controller和view通信会是怎么样呢?

controller是要把model显示在屏幕上,所以他可以对view做任何事
(Controllers can also talk directly to their View)

例如设个标志,让view做些东西,在屏幕上排列view,数据通信

看见单词outlet,outlet是一个表达式,用来表示controller的用来和view通信的一个属性

所以我们要在controller里创建outlets传到view中去

3.那么model和view是怎样的呢?

它们永远不会相互通信(The Model and View should never speak to each other)

我相信你们都理解为什么model不和view通信,因为model和用户交互界面无关

model是完全UI独立的

有些人会说,我有一些自定义view,掌控着model,所以能够显示model。这听起来挺吸引人的,但这不是个好主意的原因—重用。因为你把view和model连在了一起,model变了以后view要重写,view不能被重复利用,model也不能被其他UI用。比如iPad出来了,因为屏幕大小原因需要一个新的UI,你就得要重写整个view。最好是把这部分放到controller里,建一些更通用的view对象。另一个原因是,如果view和model通信,那么现在所有人能和model通信了,view在和model通信,controller在和model通信,model就有点hold不住了。如果只有controller在和model通信就能容易很多搞清楚程序在干什么,把view排除在外,view只是controller的仆人,让controller来通信。

4.view能否允许和controller通信?

答案是某种程度上是可以的,view(通用的)和 controller(详细控制如何在屏幕展现model)之间的通信是不可见的,view不知道自己在和谁说话。但有一个好的架构,所以Xcode里我们有组织的连接view和它的controller。所以,view向controller通信的方法,有结构的方法,一个被称为target action。target action很简单,就是controller自己画了一个target,然后把一个action交给他的view,当view发生了一些事情,比如按钮被按滑动条移动,它会把action发到target,然后controller就知道按钮被按了。这就是view向controller通信的机制,view回报controller发生了什么。但是view对controller知道的并不多,只是简单的发送target action。

事实上,还有view和controller之间比较复杂的通信,比如,view要和controller保持同步,所以常常view要告诉controller发生了什么,这是图上的did;或者将要发生什么,这是will;或者要问controller我是否允许什么发生,这是should。所以这些will、did、should是view要问的问题,这么做的原因是controller把自己设为委托(The Controller sets itself as the View’s delegate)。

用协议,设立一个协议,来回应will,did,should。

再一次,view不用知道回应的controller是哪一个类,delegation是另一个view和controller通信的方法。

另一个重要的事是,view不是它显示的数据的所有者 ( View do not own the data they display),你们要了解view不拥有数据,view只是一个平面,用来显示数据,一个显示信息的平台。view没有实体变量也不会去存储,只有指向他们的指针。比如你iPod库里的1000首歌不会是view的实体变 量,这种设计使得,比如view不会去管理数据库,更新iPod歌曲库。这不是view的活,而是controller或者model干的。

但如果view不拥有它所显示的数据,它如何获取数据呢?

一个类似delegation的方法,他有一些协议,比如这里的data at 和 count 方法。这对一个表挺有用的,表可以去问表里有多少东西 ,比如5000,那好我要在第100到第150条数据,我要用来显示。view根据需求去请求数据,这会非常高效的,如果另外一头知道怎么管理一个巨大的数据库,而只提取其中需要的几条,因为你iPod里有1000首歌,但屏幕上一次只显示7条。你要这种功能,但不要把他写在一个view里,view是通用的用来显示的,controller和model一起来有效率的提供信息。

类似的,view会有一个数据源的设置,controller会回应数据源(Controllers are almost always that data source (not Model ! )),注意,数据源的delegation永远是controller,或者是controller指定的第三方,但不可能是model,controller的工作是把model的信息传达给view,相应所有的delegation。因为它能获取model里的数据,决定怎么在屏幕上显示,这是他的职能,所以他要参与这个循环。

你们可能需要这些data at 和 count 方法,可能只是一行代码,问model数据是什么,然后model把数据给你。即使只是一行代码,也需要controller来参与,因为这是controller的工作,获取model显示在屏幕上。

上文重复了5遍“这是controller的工作”,因为这在iOS中很重要,你要给它机会做他的工作。

永远不要超过view和model之间的线。

五、还有一件事,model能向controller发话吗?

这个很明显,肯定不行的。model是UI独立的,不能向controller发话,这是controller的工作来用view显示model。那么当model的一些东西改变了,你需要更新controller的时候该怎么办呢?假设你有个数据库,某人在数据库里写了某些东西,然后比如那个人的模型的属性被外界的事物改变了,现在model改变了是因为人变胖了。在iOS里我们实现的东西是用一个广播站就像信息广播机制,有2个机制,通知和关键数据监听。当model改变了,他就在广播站广播,然后controller接收到了,去model里把什么东西改了。这个过程是无形的,也是同时的。这就是Notification & KVO。这里的kvo也可以用于view和controller,但不会是view和model,view不会有面向model的广播,view和controller会相互有广播。

model广播非常好用,因为是不可见的,所以存在限制,只能通过被允许通信的对象发生了什么事。

六、MVC群

现在我们有了各个阵营所有的通信机制,我们要建一个复杂应用。复杂应用不仅仅只有一个controller、view,它会拥有几十个controller和view。比如登陆界面,点击了什么出来了一个表,再点一下表出来个其他什么的。各种各样的view被controller管理着,那要怎么做复杂应用呢?

答案是把mvc组成mvc群。

七、controller能否可以和其他人的view对话?

通常controller只会有个指针只想另外一个controller来当做view,它会根据那个controller来显示东西。controller的工作就是获取信息,显示信息。当controller需要显示复杂的东西时,他需要其他的controller。

一个view只有一个与其搭配的controller。