1、MVC(Model-View-Controller,模型-视图-控制器)模式是相当古老的设计模式之一,它最早出现在SmallTalk语言中。MVC模式是一种复合设计模式,由“观察者”(Observer)模式、“策略”(Strategy)模式和“合成”(Composite)模式等组成。MVC模式由3个部分组成,如图
模型:保存应用数据的状态,回应视图对状态的查询,处理应用业务逻辑,完成应用的功能,将状态的变化通知视图。
视图:为用户展示信息并提供接口。用户通过视图向控制器发出动作请求,然后再向模型发出查询状态的申请,而模型状态的变化会通知给视图。
控制器:接收用户请求,根据请求更新模型。另外,控制器还会更新所选择的视图作为对用户请求的回应。控制器是视图和模型的媒介,可以降低视图和模型的耦合度,使视图和模型的权责更加清晰,从而提高开发效率。
对应哲学中的“内容”与“形式”,在MVC模型中,模式是“内容”,它存储了视图所需要的数据。视图是“型式”,是外部表现方式,而控制器是它们的媒介。
2、上面我们讨论的是通用的MVC模式,而Cocoa和Cocoa Touch框架中的MVC模式与传统的MVC模式略有不同,前者的模型与视图不能进行任何通信,所有的通信都是通过控制器完成的,如下图。
接下来我们通过一个案例来分析Cocoa Touch中MVC模式的运作过程,案例界面如上图(中)。
打开MVCSample工程,其中包括的文件有AppDelegate.h、AppDelegate.m、ViewController.h、ViewController.m和MainStoryboard.storyboard。
AppDelegate是应用程序委托对象,ViewController是视图控制器,但没有看到视图和模型。打开故事板文件,可以看到ViewController Scene(上图右),就能看到View,其中直接使用了UIKit框架中的UIView,因此在MVCSample组中没有视图,属于视图的还有Button和Text Field,他们是View的子视图。那么模型对象在哪呢?模型对象很特殊,起本质是视图的“数据”。Text Field输入的内容,Button上的便签,都可以说是模型,但是模型与视图一样,有时候我们未必需要自己创建一个模型类。因此我们做开发工作时,主要是编写视图控制器。下面我们看看视图控制器ViewController.h文件的代码:
@interface ViewController : UIViewController<UITextFieldDelegate> @property (weak, nonatomic) IBOutlet UIButton *myButton;
@property (weak, nonatomic) IBOutlet UITextField *myTextField;
- (IBAction)myAction:(id)sender; @end
可以看到,ViewController.h为两个空间myButton和myTextField定义了两个IBOutlet(输出口)类型的属性。因为要通过视图控制器更新这些视图(控件也属于视图),所以我们需要把这些视图定义成输出口类型的属性。
此外,ViewController.h还定义了 - (IBAction)myAction:(id)sender; 方法以相应myButton按钮的触摸事件。该方法的返回类型是IBAction(动作事件),这说明该方法可以相应控制事件的。
另外,ViewController还实现了UITextFieldDelegate协议,这样ViewController就变成了UITextField空间的委托对象,它们之间的运作关系如图:
①当用户触摸myButton的时候会触发ViewController中的 - (IBAction)myAction:(id)sender 方法。
②视图控制器会实现一些空间委托和数据源协议,这要看具体的控件。在此案例中,ViewController实现了UITextFiledDelegate协议,其中定义了一些相应UITextField事件的方法。
③视图控制器通过属性myButton和myTextField来改变控件的状态。
④模型对象可以通过通知和KVO机制来通知数据的变化。
⑤视图控制器可以保存一个模型成员变量或属性,并通过它们改变模型的状态。
资料:《iOS开发指南》