如何对 ViewController 瘦身

objc.io 是一个非常有名的 iOS 开发博客,它上面的第一课 《Lighter View Controllers》 上就讲了很多这样的技巧,我们先总结一下它里面的观点:

  • 将 UITableView 的 Data Source 分离到另外一个类中。
  • 将数据获取和转换的逻辑分别到另外一个类中。
  • 将拼装控件的逻辑,分离到另外一个类中。

你想明白了吗?其实 MVC 虽然只有三层,但是它并没有限制你只能有三层。所以,我们可以将 Controller 里面过于臃肿的逻辑抽取出来,形成新的可复用模块或架构层次。

我个人对于逻辑的抽取,有以下总结。

将网络请求抽象到单独的类中

新手写代码,直接就在 Controller 里面用 AFNetworking 发一个请求,请求的完数据直接就传递给 View。入门一些的同学,知道把这些请求代码移到另外一个静态类里面。但是我觉得还不够,所以我建议将每一个网络请求直接封装成类。

把每一个网络请求封装成对象其实是使用了设计模式中的 Command 模式,它有以下好处:

  • 将网络请求与具体的第三方库依赖隔离,方便以后更换底层的网络库。实际上我们公司的 iOS 客户端最初是基于 ASIHttpRequest 的,我们只花了两天,就很轻松地切换到了 AFNetworking
  • 方便在基类中处理公共逻辑,例如猿题库的数据版本号信息就统一在基类中处理。
  • 方便在基类中处理缓存逻辑,以及其它一些公共逻辑。
  • 方便做对象的持久化。

大家如果感兴趣,可以看我们公司开源的 iOS 网络库:YTKNetwork。它在这种思考的指导下,不但将 Controller 中的代码瘦身,而且进一步演化和加强,现在它还支持诸如复杂网络请求管理,断点续传,插件机制,JSON 合法性检查等功能。

这部分代码从 Controller 中剥离出来后,不但简化了 Controller 中的逻辑,也达到了网络层的代码复用的效果。

将界面的拼装抽象到专门的类中

新手写代码,喜欢在 Controller 中把一个个 UILabel ,UIButton,UITextField 往 self.view 上用 addSubView 方法放。我建议大家可以用两种办法把这些代码从 Controller 中剥离。

方法一:构造专门的 UIView 的子类,来负责这些控件的拼装。这是最彻底和优雅的方式,不过稍微麻烦一些的是,你需要把这些控件的事件回调先接管,再都一一暴露回 Controller。

方法二:用一个静态的 Util 类,帮助你做 UIView 的拼装工作。这种方式稍微做得不太彻底,但是比较简单。

对于一些能复用的 UI 控件,我建议用方法一。如果项目工程比较复杂,我也建议用方法一。如果项目太紧,另外相关项目的代码量也不多,可以尝试方法二。

构造 ViewModel

谁说 MVC 就不能用 ViewModel 的?MVVM 的优点我们一样可以借鉴。具体做法就是将 ViewController 给 View 传递数据这个过程,抽象成构造 ViewModel 的过程。

这样抽象之后,View 只接受 ViewModel,而 Controller 只需要传递 ViewModel 这么一行代码。而另外构造 ViewModel 的过程,我们就可以移动到另外的类中了。

在具体实践中,我建议大家专门创建构造 ViewModel 工厂类,参见 工厂模式。另外,也可以专门将数据存取都抽将到一个 Service 层,由这层来提供 ViewModel 的获取。

专门构造存储类

刚刚说到 ViewModel 的构造可以抽奖到一个 Service 层。与此相应的,数据的存储也应该由专门的对象来做。在小猿搜题项目中,我们由一个叫 UserAgent 的类,专门来处理本地数据的存取。

数据存取放在专门的类中,就可以针对存取做额外的事情了。比如:

  • 对一些热点数据增加缓存
  • 处理数据迁移相关的逻辑

如果要做得更细,可以把存储引擎再抽象出一层。这样你就可以方便地切换存储的底层,例如从 sqlite 切换到 key-value 的存储引擎等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值