如何对 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 的存储引擎等。

ViewController中添加子ViewController可以使用以下步骤: 1.创建子ViewController 首先,需要创建一个子ViewController,可以使用以下代码: ``` let childViewController = ChildViewController() ``` 其中ChildViewController是你要添加的子ViewController类。 2.将子ViewController添加为子视图控制器 在将子ViewController添加到父ViewController之前,需要将其添加为父ViewController的子视图控制器。可以使用以下代码将子ViewController添加到父视图控制器中: ``` addChild(childViewController) ``` 注意,这里的addChild方法不仅将子ViewController添加为子视图控制器,还会将子ViewController的视图添加为父ViewController的视图层次结构中。 3.将子ViewController的视图添加到父ViewController中 现在,可以将子ViewController的视图添加到父ViewController中,可以使用以下代码: ``` view.addSubview(childViewController.view) ``` 这里,我们将子ViewController的视图添加到父ViewController的view中。 4.完成添加 最后,需要调用以下代码来完成添加: ``` childViewController.didMove(toParent: self) ``` 这里,我们调用了childViewController的didMove(toParent:)方法,通知子ViewController已经添加到了父ViewController中。 完整的代码如下所示: ``` let childViewController = ChildViewController() addChild(childViewController) view.addSubview(childViewController.view) childViewController.didMove(toParent: self) ``` 需要注意的是,在移除子ViewController时,需要按照相反的顺序执行上述步骤,并在最后调用以下方法来从父视图控制器中删除子视图控制器: ``` childViewController.removeFromParent() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值