一个木匠

zqqf16 的个人博客

谈谈 iOS 中的 MVVM

前言

很久没写博客了,一方面因为工作太忙,把精力都耗掉了。另一方面,由于长时间不写文章,不知道该如何下笔,越来越犹豫。

前几天查看了一下最近的 Google 统计,发现我的小 Blog 竟然每天都有3、5个人访问。顿时就感觉到信心大增,为了对得起观众,我决定重新拾起来。

今天就总结一下这一阶段 iOS 开发相关的经验。

注:鄙人搞 iOS 不到 1 年,才疏学浅,如有不对之处请指教。


刚开始学 iOS 开发的时候,看的所有教程、实例为了简单起见,都会把应用的逻辑控制部分放在 View Controller 里。后来接手公司 iOS 项目时,里面的代码也是这样实现的,久而久之也就养成了这样的习惯。

随着开发的进行,代码逻辑越来越复杂,用户响应、网络交互、数据获取…等各种复杂东西都习惯性的扔到了 View Controller 里。再加上需求经常变化,为了追求稳定,通常会采用最小修改的原则,在原来设计好的逻辑下加一些“跳线”,跳来跳去~

这样做的后果就是代码耦合度大增,逻辑混乱。一个 View Controller 的实现文件轻轻松松达到3、4百行。

这样的问题大牛们早就遇到了,他们弄出了 MVVM 的概念来解决这个问题,有关 MVVM 的介绍可以参考 Objc.io 上的这篇文章 Introduction to MVVM ,大多数认都应该看过了吧~ 这里我就不再详细介绍了,只谈谈自己的理解。

所谓的 MVVM,就是在 View Controller 与 Model 之间加了一个叫 “View Model” 的层。把 iOS 中原本的 View 与 View Controller 合并到一个新的 “View”。

View | View Controller  <--------> View Model <--------> Model

新的 View 层负责所有的显示与用户交互之类的工作,而其它的,那些原本属于 View Controller 的工作全部交由 View Model 曾来处理,View 的工作能省则省。

例如,如果要显示用户的全名,而 Model 里却分别存储着用户的名与姓,那么把姓名合在一起的工作交给 View Model 来做,View 只负责显示。

再例如,如果要实现一个用户登录的功能,View 只负责把用户点击按钮的事件告诉 View Model,设置好 Delegate 或者回掉,其余的输入验证、网络交互等工作就交给 View Model 处理。

可见,MVVM 的中心思想就是分离。角色分离,视图与逻辑分离。通过分离,使各层之间耦合度降到最低。这样能够方便地对每个部分进行独立的单元测试,减少 Bug 的出现几率。同时也能满足需求的多变,如果分离合理,那么每次需求变化的时候需要进行的改动将会很小,不至于“牵一发而动全身”。

前一段时间我开发了公司的一个新客户端,采用了 MVVM 的思想。下面将将结合自己的开发经验来谈谈其中的感受。

  • 先实现功能,后谈架构

    对于这点我有十分痛苦的领悟…… 你永远不知道下一步会添加什么需求,有时候自认为设计出了合理的架构,随着 PM 新需求的一声令下,重构。

    这就有点像建篱笆围竹子,鬼知道竹子的根会绵延到哪。今天刚建好,感觉把竹子围住了,过两天就会发现篱笆外又冒出了竹笋……

    当然,有经验的人在一开始就会意识到可能会出现的问题,设计合理的架构,但这种能力也是在不断的重构过程中积累的。

    对于像我一样的初学者,个人建议先把功能实现,然后在修改需求、添加功能的时候一步一步优化架构,不要想着一步到位。

  • 分离,再分离

    这应该是设计模式里面经常提及的内容,架构设计之根本。

    MVVM 中每一层都可以细分出更小的层,当某一层代码超过了一定行数(我觉得200行就够了),就要考虑一下是否可以细分出更小的层。

    比如把 Table View 的 Data Source 分离,把 View Model 中的事件处理与 Model 操作分离。如果某一部分过于庞大,MVVM 也就失去了意义。

  • 没有最好的,只有最合适的

    没有一个能称得上是绝对好的架构,不同应用有着不同的场景,合适的才是最好的。

    比如有时候 VIPER 很合适大型应用,但是如果应用很简单,那绝对是浪费脑细胞。

  • ReactiveCocoa

    所有谈到 iOS MVVM 的文章没有不提及 ReactiveCocoa 的,我也研究过,但是后来放弃了。放弃的原因是我觉得自己才入门,应该从基础的东西一点点学起。就像学 Javascript 的时候不直接用 JQuery 一样。

    可能以后我会在自己的私人项目中尝试一下它~

  • 多看别人代码

    很多牛人在这些问题上已经走在了前面,他们的经验值得好好学习,能少走不少弯路。

参考文章: