如何给UIViewController瘦身

  随着程序逻辑复杂度的提高,你是否也发现了App中一些ViewController的代码行数急剧增多,达到了2,3千行,甚至更多。这时如果想再添加一点功能或者修改现有逻辑变得让人无比头疼。如果你遇到了这类问题,那是时候停下来了,思考一下如何更好地组织代码,给VC瘦身。本文将会阐述如何结合MVC的思想帮你的VC瘦身同时提高复用和可扩展性。

一、开发中常见的现象和缺点

  iOS中最常见的一种设计模式就是MVC,但在实际开发过程中,我们因为这样、那样的原因让单纯的ViewController变成了集Model,Controller以及View的一个大集合,这样势必就会导致VC的代码容量呈几何增长。这样的代码会存在以下几个问题:

  1、不利于后续维护

  代码在一个公司的存活时间通常远长于你在公司的时间,你是否也在接手现有项目以后边看代码边在心里默念“a piece of shit”,我想没有一个人希望之后接手你代码的人有一天看你代码的时候也在心里默念着同样的话。作为一个有追求的程序员,或者说为了不被以后的同事骂,我们必须要为自己的代码负责,避免动辄就是几千行的一个源文件。你自己写的都不愿因看,更何况后续接手的人呢。

  如果项目进度很赶,当时没有时间对代码进行合理的拆分和重构,后续也一定要抽出时间来填一下自己挖的坑。你可能会说,公司一直都很忙没有时间留给你去重构。我只能说要不就是你自己不会安排时间,要不就是这个公司只把你当代码搬运工。站在长远发展的角度上,要么改变自己,要么炒了老板。

  2、不利于支撑UI的变动

  试想如果有一天你们的App的UI风格需要改变,大量的View需要改变,在一个几千行的VC中删删改改是什么感受。可能因为改动UI的时候一个不留神错改了Model或者Controller的东西,导致程序都不能正常运行。而且改动的范围不能控制在一个较小的范围,测试回归起来的工作量也是很大的。

  3、不利于复用

  如果你的App一开始只支持iPhone版本,所有的一切都那么自然,程序也运行的很好。突然有一天老板告诉你说公司业务发展的不错,为了扩大市场需要退出iPad版,这个时候如果仅仅只是iPhone版本的放大版,那么你需要做的可能就是添加一些view的自适应就好了。但现实并不总是理想,如果iPad版的需要重新设计,按钮的位置都变动了(参考上面的第二点),这个时候难道需要把所有的代码都改一遍?这尼玛工作量也太巨大了吧。

  通常iPhone版本和iPad版本不管UI怎么变,业务逻辑只是基本相同的,那么如果当初我们的代码层级比较清晰,是不是Controller和Model层就可以完美的复用呢,针对不同的版本换一套View即可,这个是不是方便多了,自己感受一下。

二、如何解决这些问题

  第一部分说了这么多终于点题了,如何使用MVC模式更好的给VC瘦身,提高复用性和可维护性呢?我画了下面一个图:

  解释一下上面这幅图,一个完整的模块被分为了三个相对独立的部分,分别是Model,View,Controller,对应到我们App中的依次为继承自NSObject的数据中心,承载UI展示和事件响应的View以及我们最最常用的UIViewController。

  其中VC持有View和Model部分,View通过代理或者Target-Action的方式把用户的操作传递给VC,VC负责根据不同的用户行为做出不同响应。如果需要加载或刷新数据则直接调用Model暴露的接口,如果数据可以同步拿到,则直接使用获取到的数据刷新View。如果数据需要通过网络请求等其他异步的方式获取,VC则通过监听Model发出的数据更新(成功或失败)通知,在收到通知时根据成功或者失败对View进行相应的刷新操作。可以看出来整个过程中View和Model是没有直接交互的,所有的操作都是通过VC进行协调的。

  进过MVC分层的好处:

  1、VC代码量骤降,易于维护

  可以看到拆分后VC中就仅剩下事件的响应操作了,所有显示相关的东西都被单独抽取出来,所有的网络请求以及数据缓存都被提取到出去了。VC中的代码会大幅度减少,在我们项目中的实践结果为:拆分前一个VC的代码行数为2600行,拆分后VC的代码行数仅剩不到600行。

  2、复用性提高

  拆分后如果App需要对UI展示进行大改,那么你的改动基本上都会停留在View模块中,你可以选择在现有的基础上改,也可以选择从写一个。只要业务不变的话,Model和VC模块完全不需要修改。这样改动的范围较小,对开发和测试都比较友好。

  拆分后如果App需要支持iPad版本,那么你需要做的就只是重写一个View然后放进去就好了,Model和VC模块同样基本上不要做任何修改,想想是不是还有点儿小激动呢。

三、总结

  使用MVC模式可以达到帮VC瘦身,可以到到提高复用性和可维护性的效果,同时也会让原本一个整体的业务代码,分散到各个不同的地方。实际使用中我们需要具体问题具体分析,如果一个VC中的东西本身就很简单,那么完全可以放在一起,因为即使全部放在一起也就几百行代码。例如App中常见的Copyright界面,本身就是加载一个html就搞定了,就完全没必要搞得那么复杂;如果一个VC已经很复杂,代码动辄几千行了,那么就需要拆分,达到更好的复用以及方便维护的目的。

  写了几年代码了,见过所有东西都往一个源文件里面塞的,也见过一个本就很简单的东西被设计模式搞的四分五裂的,不要为了用设计模式而用设计模式。把握好度很重要,能用子弹解决的问题就不要动大炮。

  代码重构应该是一个持久的过程,在开发的过程中就时不时的对现有不合理的地方进行重构,而不是等待问题已经很多了才想起重构来。千里之行始于足下,千里之堤溃于蚁穴。

注:smileEvday保留本文的一切权利

  转载请著名原文出处

  本文在开发过程中随时更新,欢迎交流

iOS:使用MVC模式帮ViewController瘦身的更多相关文章

  1. 【iOS 开发】iOS 开发 简介 (IOS项目文件 | MVC 模式 | 事件响应机制 | Storyboard 控制界面 | 代码控制界面 | Retina 屏幕图片适配)

    一. iOS 项目简介 1. iOS 文件简介 创建一个 HelloWorld 项目, 在这个 IOS 项目中有四个目录 : 如下图; -- HelloWorldTests 目录 : 单元测试相关的类 ...

  2. (转)如何为你的Viewcontroller瘦身

    View controllers are often the biggest files in iOS projects, and they often contain way more code t ...

  3. 如何给UIViewController瘦身

    本文转载至  http://www.cocoachina.com/ios/20141128/10356.html 随着程序逻辑复杂度的提高,你是否也发现了App中一些ViewController的代码 ...

  4. iOS UIViewController的瘦身计划

    代码的组织结构,以及为何要这样写. 那些场景适合使用子控制器,那些场景应该避免使用子控制器? 分离UITableView的数据源和UITableViewDataSource协议. MVVM的重点是Vi ...

  5. iOS架构师之路:控制器(View Controller)瘦身设计

    前言 古老的MVC架构是容易被iOS开发者理解和接受的设计模式,但是由于iOS开发的项目功能越来越负责庞大,项目代码也随之不断壮大,MVC的模糊定义导致我们的业务开发工程师很容易把大量的代码写到视图控 ...

  6. IOS设计模式之一(MVC模式,单例模式)

    iOS 设计模式-你可能已经听说过这个词,但是你真正理解它意味着什么吗?虽然大多数的开发者可能都会认为设计模式是非常重要的,然而关于设计模式这一主题的文章却不多,并且有时候我们开发者在写代码的时候也不 ...

  7. iOS控制器瘦身-面向超类编程

    今天写这篇文章的目的,是提供一种思路,来帮助大家解决控制器非常臃肿的问题,对控制器瘦身. 滴滴 老司机要开车了 如果手边有项目,不妨打开工程看一下你的控制器代码有多少行,是不是非常多?再看一下tabl ...

  8. iOS中常见的设计模式——单例模式\委托模式\观察者模式\MVC模式

    一.单例模式 1. 什么是单例模式? 在iOS应用的生命周期中,某个类只有一个实例. 2. 单例模式解决了什么问题? 想象一下,如果我们要读取文件配置信息,那么每次要读取,我们就要创建一个文件实例,然 ...

  9. iOS 安装包瘦身(下篇)

    本文来自网易云社区 作者:饶梦云 2.4. 清理无用代码 2.4.1. Dead Code Stripping Activating this setting causes the -dead_str ...

随机推荐

  1. shell实现的守护进程

    代码本来是别人那里拿来的,自己又改了下,给busybox用. #! /bin/sh PRO_PATH=/opt/myapp PROGRAM=packet_analyzer while true ; d ...

  2. python字符串格式化输出

    python格式化输出 python格式化输出有两种方式:百分号和format format的功能要比百分号方式强大,其中format独有的可以自定义字符填充空白.字符串居中显示.转换二进制.整数自动 ...

  3. Django TemplateSyntaxError Could not parse the remainder: '()'

    返回的数据是列表集合,如 n [5]: a = set() In [6]: a.add((1, 3)) In [7]: a Out[7]: {(1, 3)} 在模板中使用方式如下: {% for ar ...

  4. Redis 学习笔记

    1 Redis优势 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s . 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes ...

  5. HTML之:让网页中的<a>标签属性统一设置-如‘新窗口打开’

    在开发过程中,我们往往想在页面中,给<a>设置一个统一的默认格式,例如我们想让链接:“在新窗口打开”,我们就可以使用<base>标签 在网页中添加这段代码: <head& ...

  6. PHP之:PHP框架

    ThinkPHP - 国内PHP框架 http://www.thinkphp.cn/. OneThink-基于tp框架开发的CMS  (适于小项目) http://www.onethink.cn/. ...

  7. “K米” 软件产品评测

    第一部分 调研,评测 评测: 第一次上手体验:KTV相信很多人都有去过,大部分包厢只有哦一个点歌台,相信很多人都会烦恼于一堆人挤在小小的点歌台前点歌的样子,还有些人不太好意思跑到点歌台点歌,常常是碰到 ...

  8. 旅图beta版 asp.net web api 单元测试

    旅图 beta版 asp.net web api 单元测试 测试接口:http://120.27.7.115:1010/Help 测试目的 对每个接口单元进行测试,保证每个接口的可靠性. 单元描述 注 ...

  9. f.lux for Linux安装

    1.安装f.luxsudo add-apt-repository ppa:kilian/f.lux sudo apt-get update sudo apt-get install fluxgui 2 ...

  10. 免 sudo 使用 docker

    免 sudo 使用 docker 如果还没有 docker group 就添加一个: sudo groupadd docker 将用户加入该 group 内.然后退出并重新登录就生效啦. sudo g ...