让我们停止对ViewController长度的教条

你好 我叫Ted Bendixson,我创建了其中包含200多行代码的View Controller。

我试图掩饰多年的耻辱。 你知道是怎么回事。 您参加一个聚会,发现自己与朋友和同事随意地开玩笑。 然后,您甚至没有考虑,就不小心提到了UserProfilesTableViewController的第203行。

面孔变白。 有人将酒倒入抛光的硬木地板上。

使用MVC和MVVM,您绝不应该有任何具有超过200行代码的视图控制器,对吗? 如果您使用反应性可可,则可以将这些视图控制器的尺寸缩小到更荒谬的尺寸。

那我为什么敢这样做呢? 我迷失了方向吗?

如果您像我一样,那家伙写的那个项目就遭到了一个人的折磨,后者大声地反对在多个ViewController之间传递数据的需要。 您清理了他的烂摊子,发誓永远不要让这种情况再次发生。

但是也许您对清除过去的热情太过热情了。 您的Tiny ViewController Obsession是否提高了您的生产率,还是有碍于提高生产率?

视图控制器存在的原因

在尝试回答此问题之前,我们应该首先了解ViewController试图解决的问题。 为什么我们应该首先使用具有多个视图控制器的应用程序? 通过采用这种方法,我们可以获得什么?

我曾经认识一个初级开发人员。 他不了解在控制器之间传递数据的概念。 他认为UIKit是对开发人员的一种强加手段,迫使我们创建所有这些复杂的体系结构只是为了在屏幕之间共享数据。

他更喜欢将所有代码放在一个ViewController中,因为它更易于理解。

你不能把这些东西编起来。 他只有一个ViewController拥有许多生产应用程序。 所有的UI都是用代码完成的。 要转到其他屏幕,他必须为屏幕上的一个视图设置动画,并用另一个视图替换。

在任何给定时刻,屏幕左侧或右侧都有数十个视图。

他还使用了Interface Builder,这令人困惑,因为您永远无法在他的一个ViewController中找到任何UI元素。 这是一大堆视图,按钮,表格视图和选择器,它们彼此堆叠在一起-IBOutlets相互连接在一起。

最终,他看到了光,并学会了顺其自然。 他开始使用 UIKit,而不是反对。

使用UIKit的好处

苹果公司希望我们在我们的应用程序中使用多个ViewController子类,因为这是获得UIKit原生风格的最简单方法。 如果愿意,您始终可以决定选择流氓,但您的流氓行为会付出一定的代价。

如果您决定不在您的应用程序中创建多个视图控制器,则必须开始实现UIKit免费提供的默认行为和动画。

那要花很多时间。 您也可以将初始估计值乘以10。

我们与该原生外观相关联的许多东西都直接来自UIKit。 从一个屏幕到另一个屏幕的动画,表视图,选择器,随着键盘进入屏幕而向上移动的文本字段; 全部都是UIKit。

因此,拥有ViewController这些东西的真正原因是因为我们想与UIKit一起玩得很好。 当我们与UIKit玩得很好时,我们将免费获得所有这些本机外观的行为。

换句话说,我们可以在一个月内完成一个项目,而不是十个月。

对ViewController长度有什么影响?

没有,这就是我的意思。 我们所知道的是,每个屏幕内容都需要有自己的ViewController。 没有ViewController的上帝会下雨EXC_BAD_ACCESS因为未能使该控制器低于200行而崩溃。

这就是我们所知道的

  1. 天哪,将所有代码放入一个ViewController肯定是愚蠢的。 如果这样做,您将无法利用UIKit的本机外观。
  2. ViewController应该执行与某种View的表示有关的事情。 它本身不是模型或视图。
  3. 一些视图控制器比其他视图控制器执行更复杂的视图呈现工作。 为此,他们将需要更多代码。

我们已经讨论了第一个。 让我们分解最后两个。

ViewController应该执行与某种View的表示有关的事情

毕竟,这就是视图控制器。 这是控制某种视图的东西。 在MVC设计模式中,它是C。

至少在iOS应用程序的上下文中,Controller应该做什么?

很多事情,但是让我们看一个更有趣的例子。 超级马里奥兄弟

马里奥控制器会是什么样?

如果您有任何正常的童年时代,您就会知道马里奥是一个在跳跃时左右奔跑的角色。 他还得到一朵花儿时还吐出火球。 这是一些具有一些基本功能的相当简单的行为。

如果按A按钮,马里奥跳起来。 如果按住B按钮,他将运行。 如果您按住左手,他将左手等等。所有这些动作都需要某些软件,您可以将其称为MarioController。

MarioController应该做这些事情

  1. 响应物理按钮按下,并将其转换为Mario的动作。 当您按A时,马里奥跳。
  2. 响应释放不同的按钮,这也会影响Mario的行为。 释放B时,Mario将停止运行。

而已。 很简单 MarioController解释玩家按下按钮以控制Mario在游戏中的动作。 同样, View Controller解释iPhone用户的操作,以便控制iPhone应用程序中的单个View。

iPhone应用程序中可能执行哪些操作? 事实证明,这种方式比《超级马里奥兄弟》中的功能要多得多。

这是View Controllers应该关心的事情

这是一个非常详尽的清单。 这取决于您要呈现的模型的类型,但是其中有一些。

  1. 响应按钮的按下,轻击,双击,强制触摸,长按,滑动,平移和其他手势。
  2. 响应iPhone / iPad设备方向的更改。 当用户将手机翻转到横向时,View Controller应该处理它。
  3. 响应其他类型的用户触发的事件,例如按下主屏幕按钮退出应用程序。
  4. 响应其他事件,例如远程和本地通知。

您注意到这里的模式了吗? 正在进行很多响应。 如果有某种实体(也许是一个类)来封装所有这种响应行为,那不是很聪明吗?

等一下。 UIViewController是UIResponder的子类。

其他事情也是响应者。 UIApplication是一个UIResponder。 UIView也是UIResponder。

根据Apple的文档:

UIResponder类为响应和处理事件的对象定义一个接口。 它是UIApplicationUIView及其子类(包括UIWindow )的超类。 这些类的实例有时称为响应者对象,或简称为响应者。

简而言之,一切都归结为事件处理。 如果View Controller需要处理许多事件,则将需要更多代码。 如果它不处理太多事件,则不需要那么多代码。

以此方式来看,假设任何最大View Controller大小都变得很荒谬。 这就像在说“对不起lil”事件驱动的应用程序。 您只能处理五个事件。 再就是太多的代码。 有人说我们只能打200条电话。”

大小限制教义从何而来?

我认为这来自一个好地方,需要分开关注。 您想确保事件处理实体与与Interwebs交谈的实体是分开的,Interwebs本身与您要建模的任何现实世界实体都是分开的。

当您将关注点分离时,您自然会拥有较小的View Controller,因为更多的代码将驻留在您的其他实体中。

而且,当您没有关注点分离时,您将拥有一个巨型explody的View Controller怪兽,或者一小撮explody的View Controller怪兽。

限制代码行的功能,例如训练轮。 如果我的初级开发人员朋友只能使用200行代码,他可能已经花了更多时间阅读UIKit文档并尝试在控制器之间传递数据。

他可能发现自己并不需要完全实现UIKit免费为您提供的所有导航和动画。

因此,下一次您发现自己对View Controller的大小提出疑问时,只需问问自己,编写的方法是否与事件处理有关(即响应发生的事情)。 如果没有,您可能应该将它们移至其他实体。

另外,如果您喜欢我在这里所做的事情,或者觉得有用,或者您强烈反对并希望在一个废弃的仓库后面与我面对面,在那里他们莫名其妙地混合了熔融金属,这将在我们的高潮时消耗我们双方。长时间的争论,请推荐并遵循。