MVC做对了

或一些想法,以更好地设计您的MVC应用

我一直在写有关MVP或MVVM之类的出色架构模式的文章,但是我们软件开发人员必须问自己一个非常重要的问题:我们是否按照预期的方式使用MVC? 我们是否真的研究过MVC还是只是使用了MVC?我们是在一些古老的Objective-C教程中学到的,只是将ViewControllers像神一样实现了所有功能?

MVC:什么是MVC?

如果您了解自己的知识,并且不需要任何人提醒您有关MVC的全部信息,请随时跳到下一部分。 我将撰写有关MVC内容的简短概述。

MVC在1970年代开始在著名的Xerox Parc Alto Research实验室中使用。 当苹果家伙从Altos机器上窃取UI时,他们忘记了窃取MVC。

MVC提出的方案是将您的程序分为三层,这两层相互交互,从而自然地分离出软件的职责。 值得一提的是,MVC主要用于具有UI以及与该UI进行用户交互的应用程序。 例如,在后端实施这种模式没有多大意义。

另一个常见的错误是将整个程序视为MVC(实际上并没有错),而是一个更具哲学意义的问题,而不是一个具体的实现方法。 每个视图都应复制MVC三重奏,并且此组件应相互通信。

模型 :模型表示我们在应用程序中使用的抽象。 这可以是用户,销售,物品等。如果我们使用某种网络层,则模型可能在后端启动,并最终由我们的程序继承。

View :View代表实际的用户界面。在iOS / MacOS开发中,我们使用Xcode的Interface Builder(曾经是一个单独的工具,但在最近几年中已成为Xcode的一部分)创建Views。 尽管我们可能实际上并未编写View的代码,

Controller :(或实际上是ViewController )如图2所示,这是Model-View-Controller模式的核心组件。 控制器是您应用程序内部结构的基础。 每个应用程序至少都有一个视图控制器,大多数应用程序都有多个。 每个视图控制器管理应用程序用户界面的一部分,以及该界面与基础数据之间的交互。 ViewControllers是我们实现MVC控制器部分的重要部分,但不是唯一的一部分。 我们将在本文中进一步讨论其他类型的Controller。 如Apple文档所述:

对于iOS应用程序,视图控制器提供了应用程序数据与其外观之间的重要链接。 了解何时以及如何使用视图控制器对于iOS应用程序的设计至关重要。 视图控制器是“模型-视图-控制器”设计范例中的传统控制器对象,但它们还有很多其他功能。 在iOS应用程序中,视图控制器提供了管理基本应用程序行为所需的大部分逻辑。 例如,视图控制器管理屏幕上内容的呈现和删除,并响应于设备方向的变化来管理视图的重新定向。

可以合并由和对象扮演的MVC角色,例如,使一个对象同时满足控制器和视图角色的要求,在该角色中,它被称为视图控制器。

MVC并不是真正地构建整个应用程序,它专注于与用户交谈时进行结构化以及用户如何使用它。 如果您正在使用数据库密集型应用程序,那么这可能不是最佳架构。

MVC在每个视图中实现

要牢记的一件重要事情(我实际上与我的一位同事进行过讨论,他的经验非常丰富,所以我想这可能会对其他人有所帮助)是MVC并不是您应用于应用程序的模式作为一个整体,而是在每个应用程序视图中重复执行的操作。 正如我们在一个假设的应用程序的图3上看到的那样,MVC模式在每个View上不断重复。

MVC面临着“大型视图控制器”综合症或问题:我们实际上拥有这些庞大的ViewController,它们可以处理所有事情:网络呼叫,业务逻辑,数据解析, 人类牺牲,猫狗共处……歇斯底里! 一切都交织在一起,解析器在解析完成后更新了UI(为什么不呢?)

如果这个问题没有道理,答案也不是:任何显然不是数据或显然是图形的东西都会被放入无定形的“控制器”集合中,这最终将整个代码库吸入内部,就像黑洞在其下方塌陷一样。自重” Graham Lee,Inside-Out Apps

ViewControllers是您的朋友

避免使用这种可怕的,巨大的ViewController的一个好主意是让多个ViewController控制显示给用户的实际View,而不是使用一个由较小ViewController组成的复合ViewController,自iOS 5起可用

您可以用几个ViewController填充屏幕,我们不必认为ViewController = Screen,也不必那样! 视图是可组合的 ,这意味着我们可以使用粘合在一起的各种ViewController来创建视图,并使用户感觉这是一回事。 “子视图控制器对ViewController而言,子视图对UIView而言” [1]

这有助于创建可在您正在构建的应用程序中重用的组件。 为某种特殊的按钮或标签以及(为什么)一个UIViewController(可能在整个应用程序中重复使用)成像。

这将带来更多的可读性,易于维护,并鼓励代码的重复使用(在项目内和新项目中),并具有所有这些优点。 话虽这么说,一个人必须负责

这实际上是完成此操作的方式。 使用Xcode,我创建了MainViewController,它基本上包含3个视图,供我参考(并使用AutoLayout进行操作)

这是MainViewController的代码

这样,我们就可以分离出可能在多个视图控制器之间重复的通用功能和代码。 我们还封装了这些功能并在不同组件之间共享代码,例如,我们可能只对网络服务实施一项更改,这会影响所有使用该服务的View Controller。

用户会话控制器

另一个想法是拥有一个处理登录并保存会话的对象。 这样的想法是,应用程序内需要获取有关会话的信息的任何对象都可以与此对象进行交互。

基本上,这个想法是创建一个名为UserSessionController的对象,该对象负责与Login提供程序进行交互并生成凭据,令牌等。一旦证明了用户的身份,提供程序便可以将会话信息保存在磁盘或内存中(取决于客户端要求),并为使用该服务的所有ViewController提供接口,从而为不同的情况显示适当的UI(无论用户是否登录,HomeView的填充方式都不同,等等)。

模型控制器

如果我们仔细检查了苹果的文档,就会发现有些模式我们不知道在哪里,或者也许我们读过它们却忘了。 苹果公司建议我们使用ModelControllers以及使用ViewControllers。

在很多情况下,这在您开发的应用程序可能不以UI为中心的情况下非常有用,或者也许绝对不是UI应用程序。 也许这是一个基于文档的应用程序(例如,设想一个笔记应用程序)。

包装代表和数据源

另一个想法是使用对象来处理UITableView或UIViewCollection对象委托和数据源。 这将有助于我们使ViewController更加纤薄,并且在不同组件之间的职责也大相径庭。 同样(可能是这样),我们的应用程序可能会在给定的UITableView上显示几个不同的东西,没有比交换数据源和重绘UITableView更简单的了。 对于用户而言,有多个对象来实现此目的并正确执行对于用户来说是完全相同的事情,但是对于处理您的应用程序的其他程序员而言,情况却截然不同。

您也可以为一个复杂的屏幕提供多个数据源

结论

尽管对于Massive View Controllers并没有唯一的解决方案,但是我们当然可以使用本文中介绍的一些技术来尝试使View Controller不再像神一般的类来控制所有内容,并开始将大型组件切成更小的零件。

我们已经描述了可以拆分View Controller的几种方法(拆散UI组件,拆分功能,使用服务等),并非必须同时使用所有这些技术,但是它们只是一个想法,在考虑给定应用程序设计的基础体系结构时。