AppDelegate
在iOS开发中,AppDelegate指的是UIApplicationDelegate,用来处理App层面的事件,包括生命周期变化,OpenURL,处理HandOff和Intent等。
每个iOS都有一个入口函数main,其中的一个参数就是AppDelegate:
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([QTAppDelegate class]));
}
}
痛点
由于AppDelegate是一个单例,所以通常写代码的方式:
- import对应的业务类进来
- 实现对应Delegate的方法,然后调用业务类
#import "TokenService.h"
....
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
[TokenService update:deviceToken];
}
乍一看这也没什么问题,但是随着时间的推移:
didFinishLaunchingWithOptions
堆积了越来越多的代码,有些时候这些代码还有先后顺序,比如Crash收集代码就要最早初始化。- 由于不同的模块负责处理不同的功能,比如路由模块处理OpenURL,Siri模块处理Intent….,结果就是这个文件import的类和模块越来越多,文件越来越臃肿。
日积月累:这个文件耦合越来越严重,越来越难以迭代和维护。
组件化
组件化是一个很热的概念,但并不是每个App都适合组件化,适不适合组件化要写的内容太多,以后有时间了再聊聊这方面。我们先来聊聊组件化需要翻过的几座大山:
App层面的事件如何通知到各个组件。这些事件包括应用内部的全局事件和系统层面的AppDelegate事件。
组件之间如何相互调用。通常有几种解决方案:
- 每个组件暴露抽象的协议或者抽象类出来,由一个中介者去负责创建和协调。
- 通过路由URL来相互调用。
- 暴露特定的类和方法出来,通过Target/Action的方式来调用。
组件之间的页面跳转。解决方案基本都是路由,通过URL来注册和跳转,路由还可以统一处理内跳和外跳。
可见,如果你想要组件化,那么对AppDelegate解耦是必须解决的问题。
QTEventBus
AppDelegate解耦的核心:如何让事件通知到每个模块?。
如果仅仅通知到模块,模块内部还要自己处理分发,如果支持事件可以直接通知到相关的类就更好了。
这种一对多的消息通知关系,用总线设计模式可以完美解决,所以本文的解决方案是建立在QTEventBus上的。
关于如何实现一个总线,参考我的上一篇文章:《实现一个优雅的iOS消息总线》
使用教程
安装:
pod QTEventBus/AppModule
QTAppDelegate替代默认的AppDelegate,修改main.m