iOS开发模式-MVC

MVC简介

MVC是一个基本机制,用于分类。程序中的所有对象都分到三个营地中的某一个。

 

(1)Model是对象的集合 对象是程序的行为

Model中的内容完全独立于how your UI works

在计算器中,计算是模型,是计算器要做的,应属于计算器对象,不应该在控制器中



2Controller控制Model如何显示在屏幕上

Controller中的内容明确的指出你的界面元素是如何工作的


3View是Controller的附属类(minions

View中的内容是相当通用的,通用的界面元素


三者间如何通讯

1Controller -> Model

控制器必须了解Model的一切行为,而且必须完全有能力和Model通信,根据控制器的需要,使用Model的开放API。因为控制器的职责就是使用它的附属(即View)来把Model展示给用户,所以它必须拥有该权限。这是个单向箭头。


2Controller -> View

ControllerView是允许通信的。因为控制器负责通过自身对象向视图发送指令,视图是控制器设计用户界面的新方式,因此,控制器可以做任何它想做的事。当我们有一个控制器的属性,该属性指向视图,我们称它为 Outlet,这样,控制器就可以发送指令到对应的视图。

3Model -> View  OR  View -> Model

Never!!!Model是完全独立于UI,因此,Model不能和视图层的任何对象通讯。同样的,视图对象不能和任何特定的Model对象通讯,他们需要用一个控制器来传到信息。

Never go across that line, Never.


4View -> Controller

视图对象例如button可以与控制器通信,但是你必须小心,因为视图对象是通用的(generic),所以它们不能真正的了解控制器,不知道它们所通信的类在什么位置,只是用一种盲目的结构化的方式与控制器通信。举个例子:

 

4.1target action

控制器本身写下一个target,然后它分出一个action指向View并和View通信,就像一个箭头。当你做了一个操作,比如你是一个button,别人点击了你,或者你是个拖动条,别人移动了你,就会向我发送action。通过这种方式,button或slider就可以和控制器通信,但是不知道这是一个什么类型的控制器是纸牌游戏控制器还是空间游戏控制器。它只知道当某个事件在它身上发生时,它发送一个消息给target这就是视图和控制器之间通信盲目的,简单的,结构化的方式


4.2delegate

有时,发生在视图上的事件是比较复杂的,Controller需要知道正在发生的事是什么,同步正在发生的事件。


当我正在一个scroll视图中到处滚动,我想让Controller知道我刚刚做了(did滚动操作,或者我按住屏幕,将要滑动,我想让Controller知道我将要执行(will滑动操作,或者scrollViewer需要知道是否允许(should用户在这里执行滚动操作。

scroll视图本身没有足够的逻辑知道些问题的答案所以做的事情是,代理给其他对象来回答些问题它并不知道那个对象的类是什么,他所知道的只是另一个对象可以回答这些问题,will, should, did, this, that, 或者其他事情

你将在代理协议中看到它们,协议一种和其他对象通信的盲目方式


4.3data source

另一个重要的事情是,View不应该展示的数据换句话说,数据不应该作为View内部的属性

比如说,你的iPhone中可能有10000首歌曲。假如在你的View有一些通用的视图列表,你不能传递10000首歌到它的实例变量中,并期望它能容纳10000首歌来展示给你看

第一,这样做很低效,第二,这10000首歌属于哪一层?在Model。因为你的音乐数据库是一个Model,它和UI没有任何关系,View仅仅是歌曲,艺术家,专辑和其他信息的一个列表。某个Controller必须查询这个数据库并告诉一个View如何展示这些歌曲,所以这里需要产生通信。视图展示列表分类,并且当你按下屏幕,你轻轻滑动列表,试图查看更多歌曲。这些通信是如何发生的?答案是我们有另一种特殊的代理:数据源。数据源并不做 will, did, should等事情,它回答数量等等的问题,像有多少首歌。Controller在Model中查找,把10000返回给视图。视图为10000个东西开辟内部空间,视图并不知道这些东西是什么

当你滑动滚动条,它发送消息给Controller,比如返回150行后的10条数据,然后你再往下滑,现在显示250行后的另10条数据,此时Controller再次与Model通信,要求得到更多的数据。Controller就是用这种盲目的方式提供数据给View。所以View如何从Model得到数据答案就是通过Controller用这种blind structured方式实现的所以数据源是一种用于获取数据的特殊类型代理大部分高级类都有代理,包括will,did,should,其中一些有数据源,这取决于是否要显示大量数据。而一些简单的数据,比如我给纸牌游戏创建了一个叫PlayingCardView的视图,它有花色和点数两点属性,我们不计算花色和点数,我们把它们设置成属性,所以View里会有设置好的数据,但是它不会拥有这些数据花色和点数的拥有者仍然是ModelView仅仅是为了显示而获取那些数据所以对于简单的数据,我们可能会把它传递到View里,但是只是给View来显示。对此,Controller的工作是给View解释并格式化这些Model提供的数据

5Model -> Controller

Model可以和Controller通信吗?不可以!Model对于UI一无所知,所以它不可能像Controller一样与一个UI对象进行通信

但是有时Model中的数据变了,Controller需要知道这个变化,我们怎样进行这种通信呢?

这可以通过一种电台的模型来理解。

Model也就是电台,会把信息广播给任何感兴趣的人。

iOS中为了解决这种问题而使用的技术我们叫做NotificationKVOKey Value Observing。当Model中的东西发生了变化,它会通过电台广播一下,随后,Controller会接收到来自电台的信息,它会发现数据在变化,然后它就会通过它的绿箭头与Model进行通信,给我那个改变过的数据。

 

有些人会问,View可以接收广播吗?它们也许可以,但是你最好不要这样做因为样会违背MVC的原则

6MVC -> MVC

我们有这些很好的通信方式和所有的这些规则,可以制作一些小的应用。但是如果我们想要制作一个巨大复杂的应用呢?

一个应用在iPhoneiPad上运行,有多个屏幕,在屏幕上有三个或四个不同的区域都发生着事情,我们该怎么做?

我们会结合多个MVC,因为一个MVC可以将另一个MVC当做视图的一部分,所以一个完整的MVC可以被一个稍大些的MVC当做附属(minions使用。我们可以一层一层地这样堆叠,就可以制作出越来越复杂的应用。

 

例如一个日历应用,它展示给你一整年的信息。随后你点击了一个月份,于是它展示给你月视图,月视图看起来和年视图就不太一样了。一个月视图只含有日期,也许在日期上会有一些通知你在某天会有任务的圈圈。随后,你点击了一天,然后你获得了一个日视图,日视图会显示小时信息和这天你的所有任务,随后你点击了任务,你会获得任务视图,它会显示任务的细节。这些View,年视图,月视图,日视图,任务视图,每一个都有他们自己的MVC。但是你可以发现,后三个View都被顶层的年视图当做附属使用来展示更多的细节。

你也在带有tabBarController的应用中见过这些吧。在底部有一个tab bar,有三或四个项可以供你选择,就像这张图片一样。

找到'together' 下面的那个紫色的MVC它从View指向了另外三个MVC,这就是我们创建tab bar的方式,它们就是它的三个tabs它们每一个都有完全独立的,可以独自行动的小MVC。它们每一个都是一个可重用的View,它们甚至不知道自己在tab bar,只知道自己应该做这些事情。所以在这方面,它们是模块化的。

 

我们当然不希望设计成这样

所有人都在互相通信,我们不能分清谁在和什么通信,这会让调试程序变得异常艰难,而且它无法规模化,你不能通过这种方式创建出大程序,因为你无法弄清楚,什么地方会引发整个程序的崩溃。所以我们绝对不会这样做的,这就是 MVC


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值