也谈MVVM

先说MVC吧

MVC,全称是 Model View Controller,是模型 (model)-视图 (view)-控制器 (controller) 的缩写。它表示的是一种常见的客户端软件开发框架;
MVC这个概念最早出现在上个世纪八十年代(目测本文的读者都还没有出生,当然笔者也没有出生)被提出,之后被广泛的应用于各类软件开发中.
iOS开发也不例外,iOS的系统架构就是典型的MVC,并且为我们实现了V层和C层的基础,然后开发者根据相应的数据补充M.这一切看起都很合理,而且开发者也一直都这么做着,并没有什么不妥
嗯,是的,没毛病...

但是事实真的如此么?
事实是,很多维护者会抱怨前人的代码多烂多烂,真的没法看,设计模式一塌糊涂等等;
这时候的MVC可能会变成(Massive View Controller),controller里面塞满了各类业务代码,多大上千行,甚至更多,如果注释写的好一些,勉强能看,如果没有注释...
为什么会这样?这里的原因太多了,比如有些开发者在做iOS之前并没有听说过MVC,有些即使知道MVC,也根本无法明确MVC到底干嘛的?面试官经常会问到这个问题,而得到的答案也仅仅是解释MVC概念之类,很少有人会在解释完概念之后再去仔细的阐述一下结构设计,代码规范之类...

下面我们仔细剖析一下,到底该如何MVC?

真正的MVC

我们来看看 MVC 这种架构的特点。其实设计模式很多时候是为了 Don't repeat yourself 原则来做的,该原则要求能够复用的代码要尽量复用,来保证重用。在 MVC 这种设计模式中,我们发现 ViewModel 都是符合这种原则的。

对于View来说,你如果抽象得好,那么一个App的动画效果可以很方便地移植到别的App上,而Github上也有很多UI控件,这些控件都是在View层做了很好的封装设计,使得它能够方便地开源给大家复用。

对于Model来说,它其实是用来存储业务的数据的,如果做得好,它也可以方便地复用。比如我当时在做有道云笔记 iPad 版的时候,我们就直接和iOS版复用了所有的Model层的代码。在创业做猿题库客户端时,iOSiPad 版的 Model 层代码再次被复用上了。当然,因为和业务本身的数据意义相关,Model 层的复用大多数是在一个产品内部,不太可能像 View 层那样开源给社区。

说完 ViewModel 了,那我们想想 ControllerController 有多少可以复用的?我们写完了一个 Controller 之后,可以很方便地复用它吗?结论是:非常难复用。在某些场景下,我们可能可以用addSubViewController 之类的方式复用 Controller,但它的复用场景还是非常非常少的。

如果我们能够意识到 Controller 里面的代码不便于复用,我们就能知道什么代码应该写在 Controller 里面了,那就是那些不能复用的代码。在我看来,Controller 里面就只应该存放这些不能复用的代码,这些代码包括:

  • 在初始化时,构造相应的 View 和 Model。
  • 监听 Model 层的事件,将 Model 层的数据传递到 View 层。
  • 监听 View 层的事件,并且将 View 层的事件转发到 Model 层。

MVC反面教材

直接上代码吧:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
    cell.textLabel?.text = "二狗子"
    cell.imageView?.image = UIImage(named: "")
    return cell
}

上面这段代码,咋一看也没啥,因为只有6行而已,但是这是因为上面的cell数据加载很简单,只有一个textimage,但实际开发中,我们的数据可不是这样的,如果是新浪微博那种cell我想,单单是cell的数据加载都能写个上百行;所以这种写法是完全违反MVC原则的,因为你在C里面干了V的事情, C只应该做数据传递;所以,严格遵循MVC原则的写法是,不管cell的数据加载多么负责,代码都应该是下面这样的:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
    cell.userModel = dataModel[indexPath.row]
    return cell
}

如果你的tableview是个标准的反面教材,请在评论区留下你的大名📌

这里只是简单的做了一些代码结构的调整,但是确实符合了MVC原则,但是在controller中往往不止这些东西,controller最头疼的问题,就是网络请求问题,因为复杂的界面会涉及到很多数据请求,而这些请求也会伴随着界面和数据的变化,这些逻辑写上去,那么controller的代码量瞬间就上去了,几个版本迭代过去,你懂的!所以,达到上千行只是时间问题?

何解?
在网上关于这个问题的答案有很多,比如分离网络业务层,直接放到一个专门的业务模块里面,MVVM就是在这种情况下衍生出来的.

MVVM

MVVM的历史,这里就不赘述了,感兴趣的同学直接百度,一大把,先看看一张基本上只要谈到MVVM都会放的一张图:

MVVM结构图

上面这张图,我想很多人肯定不止一次看到过

这个图准确的描述了什么是MVVM:一个MVC的增强版,让viewviewcontroller直接结合在一起,使用ViewModel进行链接,并将逻辑从controller里面移出放到ViewModel;MVVM听起来很复杂,但是他本质还是MVC,只不过在结构上做了调整;这样viewmodel彻底解耦了,那么这个时候他们之间的通信会变得有些奇怪了,因为他们中间跨越了一个层,所以在MVVM的使用当中,通常会利用双向绑定技术,使得Model的变化能同步更新到View
那么这里就得提到一个框架:ReactiveCocoa(swiftObjective - C都支持,但是在Swift上更推荐使用RxSwift);

ReactiveCocoa是一个基于Cocoa封装的函数响应式框架,使用它可以轻松的实现数据的绑定;所以,每每谈到MVVM的时候,总会提到它;但ReactiveCocoa可以不想其他三方框架那般,看看Document就可以开心的撸起来了,ReactiveCocoaDocument都能写成一本厚厚的书了,而且最关键的是,它的编程思想,函数式,响应式,数据流...
还有它那魔性的语法.

当然了ReactiveCocoa也提供了很多便捷:

  • 函数式,提供了很多函数式操作(对于Objective - C来说,Swift本身自带)
  • 数据绑定,很多时候可以代替KVO,delegate
  • 动态声明

更多信息可以去官网阅读相关文档,本文这里不做太多探讨;

要换MVVM?

既然MVVM有那么多好处,为何不换?
在移动开发领域,MVVM提出也不短了,可大部分项目还是使用MVC,只有少部分项目会用;还有一部分项目会有专门的架构师,为项目设计架构,他们会搞出一些大家都不懂的东西,然后在某个分享会上分享给大家;
但是!
我们要想清楚,你的项目真的需要MVVM么?
不一定吧?
如果你的项目本来就不复杂,为何要换?MVC就挺好的,别听那些"分享"
笔者不是说那些分享不好,好,确实好,但,那是在他们的项目上用呀,他们都是就职于BAT这样的大厂的

一笑而过?

通过上面的阅读,相信你已经对MVCMVVM有所了解,那么问题来了.

该用什么?

相信,很多iOS开发者在找工作面试的时候都被问过MVVM,基本上都快成了必问点了

我们不好说,哪个更好,哪个更适合.根据自己的情况选择
MVVM的学习路线相对要难很多,但是空闲的时候尝试一下也是个不错的实践,其中收获必定不小的
至少下次吹牛或面试的时候,你也多一些谈资不是?

生命不息,折腾不止...
I'm not a real coder, but i love it so much!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容