本文转载至  http://www.cocoachina.com/ios/20141128/10356.html

随着程序逻辑复杂度的提高,你是否也发现了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已经很复杂,代码动辄几千行了,那么就需要拆分,达到更好的复用以及方便维护的目的。

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

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

如何给UIViewController瘦身的更多相关文章

  1. iOS:使用MVC模式帮ViewController瘦身

    如何给UIViewController瘦身 随着程序逻辑复杂度的提高,你是否也发现了App中一些ViewController的代码行数急剧增多,达到了2,3千行,甚至更多.这时如果想再添加一点功能或者 ...

  2. iOS UIViewController的瘦身计划

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

  3. MVVM与Controller瘦身实践

    MVC是一个做iOS开发都知道的设计模式,也是Apple官方推荐的设计模式.实际上,Cocoa Touch就是按照MVC来设计的. 这里,我们先不讲MVC是什么,我们先来谈谈软件设计的一些原则或者说理 ...

  4. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  5. Android APK瘦身之Android Studio Lint (代码审查)

    ******** ******** 第一部分: 瘦身内容介绍 ******** ******** 项目新版本的迭代接近尾声, 因为历史累积问题, 导致有很多无效的资源让已经臃肿的APK变得更肿, 因此 ...

  6. 【直播】APP全量混淆和瘦身技术揭秘

    [直播]APP全量混淆和瘦身技术揭秘 近些年来移动APP数量呈现爆炸式的增长,黑产也从原来的PC端转移到了移动端,通过逆向手段造成数据泄漏.源码被盗.APP被山寨.破解后注入病毒或广告现象让用户苦不堪 ...

  7. APK瘦身记,如何实现高达53%的压缩效果

    作者:非戈@阿里移动安全 1.我是怎么思考这件事情的 APK是Android系统安装包的文件格式,关于这个话题其实是一个老生常谈的题目,不论是公司内部,还是外部网络,前人前辈已经总结出很多方法和规律. ...

  8. iOS可执行文件瘦身方法

    缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大 ...

  9. 清理iOS工程里无用的图片,可瘦身ipa

    工程在经过多人后,往往会出现较多的垃圾,导致打包出来的ipa文件偏大,有时候我们会通过清理代码来给程序瘦身,而瘦身ipa效果明显的,主要通过清理程序里的无用图片. 推荐一个清理图片的应用 https: ...

随机推荐

  1. php--获取用户ip

    一般在做登录的时候有的会要求同一个帐号不能同时用不同的ip登录,这个时候我们需要获取到用户IP地址 获取ip地址的函数: function getIP() { if (getenv('HTTP_CLI ...

  2. C#性能优化篇 - 基于索引器封装EPList

    using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Sy ...

  3. 解决WordPress中字符转义的问题

    wordpress中输入两个"--"的时候会识别成一个横杠,如果此时的文章中有代码在,那么其他人在复制粘贴的时候就没法使用,于是乎我寻找了三种有效的方法解决此问题! WordPre ...

  4. 洛谷——P1785 漂亮的绝杀

    P1785 漂亮的绝杀 题目背景 话说absi2011的企鹅在和斗神塔第60层的Boss战斗 不好,这局要输了,企鹅还剩4血了Boss还有392呢,哇,漂亮——红缨枪连击,280,343(暴击),绝杀 ...

  5. 洛谷——1115 最大子段和(区间DP)

    题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入输出格式 输入格式: 输入文件maxsum1.in的第一行是一个正整数N,表示了序列的长度. 第2行包含N个绝对值不大于10000 ...

  6. weight initilzation

    1. pytorch提供接口 method 1  torch.nn.init里面有很多初始化分布 import torch.nn.init as init self.conv1 = nn.Conv2d ...

  7. 【hibernate】hibernate不同版本的命名策略

    ===================================================hibernate 4命名策略如下================================ ...

  8. Java的日志模块

    目前主流的是是logback和log4j2,它们底层实现用的都是slf4j,通过slf4j-api调用 使用指定类初始化日志对象,在日志输出的时候,可以打印出日志信息所在类如:Logger logge ...

  9. MFC中 自定义消息

    想在对话框显示出来后立即执行一段代码. 方法之一是自定义消息,即添加一个自定义的消息在消息队列中等待对话框初始化之后从消息队列中读取消息执行代码. 在OnInitDialog返回之前post一个自定义 ...

  10. Git可视化极简易教程 — Git GUI使用方法

    Git可视化极简易教程 — Git GUI使用方法 学习了:http://www.runoob.com/w3cnote/git-gui-window.html