《iOS App 开发的那些事儿》系列文章从更宏观的角度出发,不仅仅局限于具体某个功能、界面的实现,而是结合网易云信 iOS 端研发负责人多年的经验,从如何优化现有代码的角度出发,深度分析如何创造出 iOS App 开发中比较合适的规范和框架。
推荐阅读
《iOS App 开发的那些事儿 1:如何建立合适的规范》
一个合适的框架不是银弹,在我看来框架要解决的问题从来不是:有了框架之后,工程就能无比正确地进行下去。好的框架能够做到的事仅仅只是:降低通用问题的复杂度和减少发生错误的可能性。个人认为一个良好 iOS App 框架应该是有如下特点:
定义清晰的层次结构
- 横向上,各模块互相独立,仅通过有限的几个接口进行通讯。最理想的状态是除核心模块外,其他模块都是可拔插。纵向上,各层次间依赖关系清晰,基本不出现逆向依赖的情况。
- 横向模块一般依赖于业务需求,常被定义成各种 Service 或 Manager。一种好的做法是有个统一的 Service 管理器负责相应 Serivce 的加载,卸载,监听和分发 App 级别的通知给相应 Service,如前后台切换,收到内存警告等。这样做一方面容易实现上面说的模块的可插拔化,另一方面也保证了公用特性处理的一致性。在这方面微信就做得不错,基本所有的模块都是从MMService继承而来,由 MMServiceCenter 进行管理。当然从 dump 出来的头文件也可以发现一些管理上的紊乱,比如一些 ViewController 都是继承自 MMService。
- 纵向的层次划分基本各个 App 不会有太大区别,一般可以分为三个层次:
展现层(Presentation layer):负责管理 UI 和 UIViewController。
逻辑层(Business/Service Layer):负责逻辑数据的定义和转发,起到承上启下的作用。
数据访问层(Data Access Layer):负责具体 API 构造,网络请求,数据持久化等。
各层根据业务逻辑的复杂性内部又会使用单层或者多层结构。以数据访问层为例,一般又可以细分为网络层,持久化层。而一般而言,展现层(UIView 和 UIViewController)都是直接使用逻辑层提供的Model进行展现,但是某些场景下往往需要不同的Model有相同的界面展示(如我们的 App 易信中,会话界面,收藏界面,问一问功能都需要进行图片的展现,但这三个模块下的 Model 定义并不一致),这就需要增加额外的 ViewModel 层用于粘合展现层和逻辑 Model。
遵守 SOLID 原则和慎用各种设计模式
这是个老生常谈的话题了,并不是 iOS 开发独有,展开讲可以讲上几天几夜,不赘述。
定义自己的UI基类:UIView,UIViewController,UITableviewCell
这一点的好处不言而喻,所有的子 View,Controller,Cell 都能够很方便的继承基类的共有的行为,样式。但也会引进很大的管理风险:组内成员总会经不起诱惑往基类塞各种并不普适的特性,引起基类权责的无限膨胀。大基类不仅增加组内成员对代码的理解难度,同时也增加出现问题时的排查难度。从这方面讲,微信的 UIViewController 基类设计就极端失败:MMUIViewController 这个类光头文件就有上百行。
提供方便好用的工具类
一些好用的工具类往往会成为框架重要的有机组成部分,方便快捷地解决局部问题,同时又不引入过多的复杂度。NSTimer 的 retain cycle 是个很容易掉去的坑,那么提供一个基于 Block 或者 weak delegate 的 NSTimer 的封装就是不错的选择。使用 KVO 容易发生 add 和 remove 的不配对调用,那么就引入THObserversAndBinders 或者 FB 的 KVOContorller。某些核心模块需要被多个模块依赖时,引入类似 XMPP 的GCDMulticastDelegate 就能够方便地进行解耦。
好的范例
在前几年使用 C++ 的那段暗无天日的日子里,我常想的一个问题是:如何在 API 层面去限制和规避一些错误。比如往线程池里面扔的 task 必须是堆上分配的对象,那么如何去强制传入的指针指向的是堆地址而不是栈地址呢?这种傻问题大部分情况下是无解的,有时候有解却是个异常别扭的解。而现在我更相信破窗理论所提供的可能性:做好示范,接下来的一切都会水到渠成。
大家可以戳《iOS App 开发的那些事儿 1:如何建立合适的规范》回顾该系列第一篇文章,也欢迎大家积极发表自己的看法,与我们共同讨论。
随着即时通讯以及音频处理和压缩技术的不断发展,效果更好、适用范围更广、性能更高的算法和新的技术必将不断涌现,如果你有好的技术或者分享,欢迎关注网易云信官方博客和 GitHub:
关注更多技术干货内容:
网易云信博客欢迎关注
网易云信 GitHub欢迎关注
网易云信官网