理解iOS的应用程序的MVC架构模式

时间:2022-06-26 17:44:42
在iOS系统上运行的应用程序遵守MVC的软件架构模式,将自己分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
MVC,*是这样定义的。
MVC模式最早由Trygve Reenskaug在1974年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式。MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。软件系统通过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组:
(控制器Controller)- 负责转发请求,对请求进行处理。
(视图View) - 界面设计人员进行图形界面设计。
(模型Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。

在iOS的应用程序中,MVC架构模式将应用程序的屏幕对象的外观和行为区分开来。屏幕上的对象如按钮,本身没有任何内在含义,它能实现的所有操作都是通过视图控制器来实现的。视图控制器是桥梁,将用户操作和应用程序中的目标方法联系起来,目标方法又读取和保存数据到应用程序中的某个数据模型里。
这是一个极其简单的iOS应用程序的架构模式。在MVC中,视图控制器的角色看成控制器,但也能看成是视图,因为它是控制视图显示的重要组成部分。

一、视图(View)

在iOS应用程序创建时,所使用的视图组件是由UIView 类的子类及与其相关的UIViewController类提供,它们分别负责定义和放置屏幕元素。UIViewController类不是MVC 模式中的控制器角色,这点和命名略有出入,就理解成这是控制视图的一个类。它负责对屏幕的各项元素进行布局。
但是,每个UIViewController子类都实现了自己的loadView方法。该方法对视图控制器的所属视图进行布局,并建立所有的触发、回调和委托。从这个角度看,它又算一个控制器。
因此,咱们理解即可,灵活使用,不必纠缠于某些条条框框,否则反而限制了自己。


二、控制器(Controller)


在iOS应用程序中,控制器的行为通过这三个技术来实现,分别是委托、目标操作和通知。

1、目标操作(target action)

它是重定向用户交互的一种较低级的方式,基本上只有在实现UIControl类的子类时,我们会遇到它们。

例如,在应用的视图界面上有一个按钮,"touch up inside",就是将执行target配置的对象和action配置的方法。
视图控制器类的代码是这样的:
 UIBarButtonItem *barListBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemAdd target:self action:@selector(getTruckStopListAction)];  
 self.navigationItem.rightBarButtonItem = barListBtn;
 [barListBtn release];
代码中定义的action是@selector(getTruckStopListAction),定义的target是视图控制器类本身即self。
在视图控制器类中应该有一个已实现的getTruckStopListAction方法,按钮"touch up inside"时触发的就是这个方法。这个方法可以看着是MVC架构模式中的控制器角色,它的定义代码可以按照需求随时修改。

这就是target-action模式。

如果target不是self,而是其他的类,那么在其他的类要实现这个action所配置的方法。这个类就是一个纯种的MVC架构模式的控制器。不像现在和视图控制器类参杂在一起,搞得不知道视图控制器类算MVC架构模式的控制器还是MVC架构模式的视图。(注,这段纯粹是个人猜测,不一定正确。)

苹果文档对于target-action 模式的定义如下:

Target-action is a design pattern in which an object holds the information necessary to send a message to another object when an event occurs. The stored information consists of two items of data: an action selector, which identifies the method to be invoked, and a target, which is the object to receive the message. The message sent when the event occurs is called an action message. Although the target can be any object, even a framework object, it is typically a custom controller that handles the action message in an application-specific way.


2、委托(delegate)

"委托"是一种简单而强大的设计模式,它可以让程序中的一个对象和另一个对象交互。例如对象A是对象B的委托即B.delegate=A,那么对象B就通过它的属性delegate发送消息给对象A即[[B delegate] message],实质上就是对象B让对象A执行message,而message的定义是在A中实现,但对象A何时执行message是由对象B来控制的。

举一个例子,对象A通过segue展现对象B,对象B再通过delegate释放自己。

对象A中的代码如下:
/*使用prepareForSegue传递数据*/
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"objectBView"]) {
        objectBViewController * objectBController=[segue destinationViewController];
        objectBController.u01=self.usernameInput.text;
        objectBController.u02=self.passwdInput.text;
        
        /*设置 被展现视图控制器的委托 为 正展现的视图控制器,即自身*/
        objectBController.delegate=self;
    }
}

/*实现协议中的方法*/
-(void)objectBViewControllerDone:(objectBViewController *)controller username:(NSString *)username passwd:(NSString *)passwd
{    
    [self dismissViewControllerAnimated:YES completion:NULL];    
}
注意,因为是在objectBViewController中执行这个方法,所以self还是objectBViewController。

对象B中的代码如下:
- (IBAction)dismissobjectBView:(id)sender
{
    [[self delegate] objectBViewControllerDone:self username:self.username.text passwd:self.passwd.text];
}

再举一个例子,创建一个UITableViews子类,当用户触击某行时,该类没有响应该触击操作的内置方式,因为这种响应责任已经移交给委托,通过委托方法tableView:didSelectRowAtIndexPath: 来处理。这个委托就在UITableViewController类的子类中实现,因此UITableViewController子类必须遵守协议UITableViewDelegate和UITableViewDataSource,实现这两个协议中的必须实现的方法。UITableViewController子类就成了UITableViews子类的委托。


委托在iOS中应用非常广泛,对它理解得越透彻,越有利于提升我们的开发能力。

苹果文档对于delegate 模式的定义如下:
Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled. The delegate may respond to the message by updating the appearance or state of itself or other objects in the application, and in some cases it can return a value that affects how an impending event is handled. The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object.
 
3、通知

它支持应用程序中的对象的交互,及与iOS系统上其他应用程序通信。对象在通知中心注册为一观察者,视为订阅。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update) name:@"update" object:nil]

 
三、模型(Model)

模型方法通过数据源和数据含义等协议提供数据,需要实现由控制器触发的回调方法。你需要创建应用程序控制器触发的回调方法,并提供所需的任何委托协议的实现。iPhone SDK 中的数据源可以帮助实现。数据源指任何向另一个对象提供所需数据的对象,其类似于委托,必须在另一个对象中实现它们的方法。它与委托的不同之处在于创建或提供对象而不是针对用户交互作出反应。

苹果文档对于Data Source模式的定义如下:
A data source is almost identical to a delegate. The difference is in the relationship with the delegating object. Instead of being delegated control of the user interface, a data source is delegated control of data. The delegating object, typically a view object such as a table view, holds a reference to its data source and occasionally asks it for the data it should display. A data source, like a delegate, must adopt a protocol and implement at minimum the required methods of that protocol. Data sources are responsible for managing the memory of the model objects they give to the delegating view.