这篇文章将帮助你避免App中常见的导致不易扩展的错误。你将会学到当你创建一个App时该怎么做,不该怎么做的最佳实践。
读完这篇文章你能学到在app中使用最新最好的实践。避免结构上的问题。
MVC101
模型是数据存放的地方。持久化、模型对象、解析器和网络相关代码这些东西通常放在这里。
视图是app的界面。这些类能被复用,一般不存放特定业务的逻辑。
控制器在模型和视图之间进行调解,典型的是通过代理模式。理想情况下,控制器实体不会知道它处理的实体视图。相反,它会通过代理和抽象视图交流。
什么去了哪儿?
尽管理解MVC的理论很容易,有时候在实际的场景指出什么去了哪儿却是比较复杂的。让我们花些时间关注一下。
视图层
当一个用户和你的App交互的时候,他们是在和视图层交流。视图被认为是App中的“哑巴”部分,因为它不应该包含任何的业务逻辑。在代码层面,你通常会看到:
UIView子类。从基本的UIView子类到复杂的自定义UIControl。
一个UIViewController(有争议)。由于一个UIViewController和它自己的根视图以及不同的生命周期强烈的耦合在一块儿,我个人认为应该属于这一层,但是并不是所有人认同。
动画和控制器转场。
UIKit/AppKit、Core Animation 和 Core Graphics的一部分。
不要为了节省时间把一堆代码都写到UIViewController里,以后你可能会花多倍的时间来找bug,或者复用里面的代码。
用下面的清单检查你的视图层:
它和模型层交互了吗?
它是否包含了任何的业务逻辑?
它是否做了和UI无关的事情?
如果上面任何一个问题的答案是yes,那么你就可能需要清理一下并重构了。
当然,这些规则没有被刻在石头上,有时你得弯曲它们。尽管如此,你得展现足够的重视。
控制器层
控制器层是app里最少复用的部分。因为它引入了你特定领域的规则。有些东西在你的app里有意义,但是在别人的app里面可能没有什么意义,这并不令人吃惊。
通常你会看到这一层的类决定着下面这些事情:
什么应该首先进入:持久化还是网络?
你应该多久刷新一次app?
下一屏应该是什么,在什么样的状况下?
如果app进入后台,什么应该被清理掉?
你应该把控制器看做app的大脑:它决定接下来发生什么。通常你会想要对这些类做大量测试以确保所有的事情按照预期运行。
建议总是让控制器是可注入的。这样,你的UIViewController的拥有者就能提供控制器。这有两方面的好处:
1、便于测试。
2、这些层会很干净,并且去耦合。这有助于定义职责,从而形成整体上更健康的代码基础。
模型层
模型层并不是像它看起来的那么能够自解释。
就如同你期望的那样,它将包含你的模型对象,基本覆盖了大部分层的界面。
MVC: Massive View Controller?
UIViewController过多的承担并不属于它的职责,最终导致Massive View Controller。它开始于积累像网络请求和数据解析这样的事情,最终越来越大以至于你失去了对信息流的追踪。更糟糕的是,你不能以一种安全的方式进行重构。因为这种方式会让单元测试变得非常困难。
针对臃肿的控制器的解决方案很难快速找到解决方案。因此它常常变成技术债务。这在iOS社区很常见,也是MVC名声被搞坏的原因。但是这不是你的命运!
作为一个一般原则,一个UIViewController不应该拥有超过130行代码。这似乎很那实现,但是如果你坚持原则,这很容易。以下是我坚持的一些原则:
1、view controller里的大部分代码和它的根视图UIView的自定义有关。
2、它应该负责把控制器和它的根视图勾连起来,例如,在一个IBAction上调用控制器方法。
3、UITableDataSource, UITableViewDelegate和其他的一些代理不应放在它里面。如果这样做,就没办法测试它们。
4、如果你的view controller里有过多的属性,你可以把他们分开到多个控制器中,或者创建一个自定义的UIView。
这些只是指导方针。有时你的UIViewController非常简单,可能就没必要创建那么多实体。
记住,你赋予view controller的每一个职责都会让你丧失测试和复用那段代码的机会。