前面明确了iOS应用开发的复杂性所在,那么从架构层面上应该如何去管理这些复杂性呢?
使用Atomic Design和Component Driven Development管理界面开发的复杂度UI界面的复杂度本质上是一个点上的复杂度,其复杂性集中在系统的某些小细节处,不会增加系统整体规划的复杂度,所以控制其复杂度的主要方式是隔离,避免一个UI组件之间的相互交织,变成一个面上的复杂度,导致复杂度不可控。在UI层,最流行的隔离方式就是组件化,在笔者之前的一篇文章《前端组件化方案》中详细解释了前端组件化方案的实施细节,这儿就不再赘述。
使用App Coordinator统一管理应用路由
应用的路由主要分为App间路由和App内路由,对它们需要分别处理
App间路由
对于APP之间的路由,主要通过两种方式实现:
一种是URL Scheme 通过在当前App中配置进行相应的设置,即可从别的APP跳转到当前APP。进入当前App之后,直接在AppDelegate中的方法:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool
转换进App内的路由。
另一种是Universal Links,同样的通过在当前App中进行配置,当用户点击URL就会跳转到当前的App里。进入当前APP之后,直接在AppDelegate中的方法:
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool
中转进App内路由。
所以App间的路由逻辑相对简单,就是一个把外部URL映射到内部路由中。这部分只需要增加一个URL Scheme或Universal Link对应到App内路由的处理逻辑即可。
App内路由
对于内部路由,我们可以引入App Coordinator来管理所有路由。App Coordinator是Soroush Khanlou在2015年的NSSpain演讲上提出的一个模式,其本质上是Martin Fowler在《 Patterns of Enterprise Application Architecture》中描述的Application Controller模式在iOS开发上的应用。其核心理念如下:
抽象出一个Coordinator对象概念
由该Coordinator对象负责ViewController的创建和配置。
由该Coordinator对象来管理所有的ViewController跳转
Coordinator可以派生子Coordinator来管理不同的Feature Flow
经过这层抽象之后,一个复杂App的路由对应关系就会如下:
从图中可以看出,应用的UI和业务逻辑被清晰的拆分开,各自有了自己清晰的职责。ViewController的初始化,ViewController之间的链接逻辑全部都转移到App Coordinator的体系中去了,ViewController则彻底变成了一个个独立的个体,其只负责:
自己界面内的子UIView组织,
接收数据并把数据绑定到对应的子UIView展示
把界面上的user action转换为业务上的user intents,然后转入App Coordinator中进行业务处理。
通过引入AppCoordinator之后,UI和业务逻辑被拆分开,各自处理自己负责的逻辑。在iOS应用中,路由的底层实现还是UINavigationController提供的present,push,pop等函数,在其之上,iOS社区出了各种封装库来更好的封装ViewController之间的跳转接口,如JLRoutes,routable-ios,MGJRouter等,在这个基础上我们来进一步思考App Coordinator,其概念核心是把ViewController跳转和业务逻辑一起抽象为user intents(用户意图),对于开发者具体使用什么样的方式实现的跳转逻辑并没有限制,而路由的实现方式在一个应用中的影响范围非常广,切换路由的实现方式基本上就是一次全App的重构(做过React应用的react-router0.13升级的朋友应该深有体会)。所以在App Coordinator的基础之上,还可以引入Protocol-Oriented Programming的概念,在App Coordinator的具体实现和ViewController之间抽象一层Protocols,把UI和业务逻辑的实现彻底抽离开。经过这层抽象之后,路由关系变化如下:
经过App Coordinator统一处理路由之后,App可以得到如下好处:
ViewController变得非常简单,成为了一个概念清晰的,独立的UI组件。这极大的增加了其可复用性。
UI和业务逻辑的抽离也增加了业务代码的可复用性,在多屏时代,当你需要为当前应用增加一个iPad版本时,只需要重新做一套iPad UI对接到当前iPhone版的App Coordinator中就完成了。
App Coordinator定义与实现的分离,UI和业务的分离让应用在做A/B Testing时变得更加容易,可以简单的使用不同实现的Coordinator,或者不同版本的ViewController即可。