IOS之MVC

MVC模式是软件工程中的一种软件架构模式。
把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

  • Model: 程序的数据部分,用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法
  • View: 程序的界面展示,实际上是数据有目的的界面显示,但视图绝不与model直接交互,在视图中一般没有程序上的逻辑;
  • Controller: 将Model与View连接起来协同工作的部分,控制器起到不同层面间的组织作用,用于控制应用程序的流程。

优点MVC使得程序的输入、处理和输出强制性的分开,这增加了软件的扩展性、维护性以及封装性,使得软件开发从不同层面上分离解耦。直接描述这些优点可能看着会很晦涩,举几个例子来说明一下:1.几个界面可以共用一个model,这使得model可复用,同时只有model的一个拷贝使得代码更易于维护;2.当模型,数据与控制器是相分离的时候,改变业务规则就变得很容易,数据的存储可以随意的迁移,因为模型对控制器的接口是不变的,这样界面仍然可以正确的展示,界面UI也是可以任意改变,因为它只关心界面不会影响到其他;3.MVC这样将三方独立的区分开,也绝对的有利于多人或者团队开发。

缺点虽然MVC有着那么多优点,并且我们的项目也采用这样的开发模式,但是他的缺点也很明显,严格的三者分离有时候是很难区分的,需要仔细的思考确定边界,同时Model与View不能直接交互,就必然在性能上有一些损失(极小)。


 了解了MVC的基本概念及思路后,我们来说说MVC在IOS开发当中的体现及实际应用。首先来看一下斯坦福公开课给出的图:

 先解释图中类似三叉路口的白线与黄线,M与V之间是两条黄线,这可以理解为两条黄色禁线,禁止了model与view的直接通信,所以说model与view是不能直接交互的,任何方向都不行;而C到M与C到V之间是一条虚线与一条实现,靠近C的是虚线,靠近M与V的为实线,可以理解为C到M或者V是可以穿越的,可以直接调用,而白色的实线则代表着你可以穿越它,可以去调用,但是得通过某种特殊方式,非直接调用,如何调用呢?下面会详细讲解到。

1 . C与M之间的关系调用。C指向M有一条绿色的线,这是直接调用关系。到实际的使用层面就是C可以通过import M的头文件任意使用M的公有API。M不能直接调用C,但是注意到了吗?model上面还有一个黄色的像小灯泡一样的东西,这个其实是M与C对话的一种间接方式。这种间接方式是什么呢?就是Notification & KVO。Notification是IOS里的另一个重要概念,C可以注册M的观察者,当M的数据发生改变后会发出通知使得它的观察者C接收到,然后做出一些响应(改变UI或者神马的);KVO(Key Value Observing)提供一种机制,当指定对象的属性被修改后,则接收到通知。Notification & KVO又是另一个可以深入探讨的话题,后续的博客也会写到。

2 . C与V之间的错综复杂的关系。C只想V也有一条绿色的线,也是直接调用关系。实际使用就是Controller可以持有View的一个指针,可以随意的调用View的公有API去改变View的展示。而View到Controller的通信代价就比较大了,具体有三种方式:

  第一种是目标操作 。target-action,view对于自己响应的action可以添加target方法,而target方法一定是存在在controller里面的方法,这样当view的某个动作发生后,就会去调用controller的方法,即view的target方法。例如,UIButton的按下操作的响应方法,可以addTarget一个方法,当按钮被按时调用这个方法,记住这个view是一个广义上的view,可以是你显示在屏幕上的一切东西,可以是系统提供的控件也可以是你自己写的view。

  第二种是委托。view制定自己的UI发生改变时的protocol,再声明一个weak的delegate属性,controller去实现view的protocol并做view的delegate。这样当它自己改变时就会询问view should I do sth?或者是当它will 或者 did change的时候就会去调用controller实现的委托方法了。委托也是IOS里面非常重要的一块内容,Coaoa提供的很多方法都是使用这种方式,比如UIAlertView。委托也会在后续博客中作为单独的一篇来写。

  第三种是数据源(data source)。V是数据的界面显示,但很显然view不可能自己拥有数据,所以在它的展示中会不断的向数据源去请求数据,而这种请求则需要通过controller来完成。比较典型的例子就是UITableView的实现,可以深入研究下(也可以作为单独的一篇来讲,比较重要)。


 下面来写段代码看一下MVC具体到代码级别到底是怎样的,V到C的调用以委托为例(很小的例子,但麻雀虽小,五脏俱全)

model的实现:

1 @interface MVCDemoModel : NSObject
2 @property(nonatomic , strong) NSString *name;
3 @end
MVCDemoModel.h
 1 @implementation MVCDemoModel
 2 
 3 -(id)init
 4 {
 5     self = [super init];
 6     if (self) {
 7         _name = @"wangqing";
 8     }
 9     return self;
10 }
11 
12 @end
MVCDemoModel.m

 view的实现:

 1 @protocol MVCDemoViewDelegate <NSObject>
 2 
 3 -(void)showModel;
 4 
 5 @end
 6 
 7 @interface MVCDemoView : UIView
 8 
 9 @property(nonatomic , weak)id<MVCDemoViewDelegate> delegate;
10 
11 @end
MVCDemoView.h
 1 @implementation MVCDemoView
 2 
 3 - (id)initWithFrame:(CGRect)frame
 4 {
 5     self = [super initWithFrame:frame];
 6     if (self) {
 7         UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(80, 200, 200, 80)];
 8         [button setTitle:@"click me" forState:UIControlStateNormal];
 9         [button setBackgroundColor:[UIColor blueColor]];
10         [button addTarget:self action:@selector(showTheModel) forControlEvents:UIControlEventTouchUpInside];
11         [self addSubview:button];
12     }
13     return self;
14 }
15 
16 - (void)showTheModel
17 {
18     if ([_delegate respondsToSelector:@selector(showModel)]) {
19         [_delegate showModel];
20     }
21 }
22 
23 @end
MVCDemoView.m

 controller的实现:

1 @interface ViewController : UIViewController<MVCDemoViewDelegate>
2 
3 @end
ViewController.h
 1 @interface ViewController ()
 2 
 3 @property(nonatomic , strong) MVCDemoModel *demoModel;
 4 @property(nonatomic , strong) MVCDemoView *demoView;
 5 
 6 @end
 7 
 8 @implementation ViewController
 9 
10 - (void)viewDidLoad
11 {
12     [super viewDidLoad];
13     _demoView = [[MVCDemoView alloc]initWithFrame:self.view.frame];
14     [_demoView setDelegate:self];
15     [self.view addSubview:_demoView];
16     
17     _demoModel = [[MVCDemoModel alloc]init];
18 }
19 
20 - (void)showModel
21 {
22     NSLog(@"my name is %@",_demoModel.name);
23 }
24 
25 @end
ViewController.m

 讲解一下上面的代码,点击+号可以展开哟~也可以复制到工程中运行。

首先,可以看到Model与View没有直接的调用关系,二者不需要引用对方的头文件。可以看见,ViewController实现了MVCDemoView的delegate方法 showModel,而MVCDemoView中在点击button后会去找这个委托实现的方法,而该方法内,由于viewController用于model使用权,所以可以直接获取到model.name并打印到控制台。这样就完成了三者的一次交互。

 

声明:本文为作者原创,代码也全部手写,如需转载请注明出处,对于本文中提到的内容如有疑问请直接留言,谢谢!

posted on 2014-01-04 22:49  好好学习_天天向上  阅读(1402)  评论(0)    收藏  举报