本文为博主原创文章,未经博主允许不得转载
AppDelegate随着我们开发的深入,里面会产生很多的初始化、生命周期处理、推送、通知等方法,这些代码对我们组件化各个独立工程的开发环境搭建有很大的影响,例如:我们单独的业务线可能不需要对生命周期有处理,但是独立开发环境的AppDelegate如果定制化过大,后续可能会产生问题,所以需要一种统一的方式,减少各工程AppDelegate的差异。
一、分模块加载AppDelegate方法
基于上述考虑,我们可以采用一种分模块加载的方式加载所有AppDelegate方法,该方式会依次加载各个模块,当主AppDelegate某个方法被调用时,会依次调用各个模块的方法,这样各个模块都存在一套自己的AppDelegate方法,互不干扰,而我们主AppDelegate里面只需要存在相应的调用代码,其余的代码都可以分散在各个工程,从而保持一份稳定且干净的AppDelegate。
1、 FRDModuleManager
FRDModuleManager是豆瓣开源的轻量级模块管理工具,它通过减小 AppDelegate 的代码量来把很多职责拆分至各个模块中去,这样 AppDelegate 会变得容易维护。其主要类 FRDModuleManager 只有 300 多行代码,使用方式也很简单。
GitHub地址:https://github.com/lincode/FRDModuleManager
- FRDModuleManager仅有三个方法
+ (instancetype)sharedInstance;
- (void)loadModulesWithPlistFile:(NSString *)plistFile;
- (NSArray<id<YRDModule>> *)allModules;
- FRDModuleManager通过读取plist数组存放的module名称完成初始化,将module全部加载起来:
let plistPath = Bundle.main.path(forResource: "ModulesRegister", ofType: "plist");
let manager = YRDModuleManager.sharedInstance();
manager?.loadModules(withPlistFile: plistPath);
- 在主AppDelegate中分别添加调用方法,这里使用了自己维护的module管理器:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
YRDModuleManager.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions);
return true
}
func applicationWillResignActive(_ application: UIApplication) {
YRDModuleManager.sharedInstance().applicationWillResignActive(application);
}
func applicationDidEnterBackground(_ application: UIApplication) {
YRDModuleManager.sharedInstance().applicationDidEnterBackground(application);
}
- 在各个模块的生命周期类中,添加钩子函数
//需要遵守的协议
<UIApplicationDelegate, UNUserNotificationCenterDelegate>
各自的模块中钩子函数:
@implementation YRDPlatformModule
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSLog(@"%@ Timeline", NSStringFromSelector(_cmd));
return YES;
}
2、JSDecoupledAppDelegate
JSDecoupledAppDelegate 是由 JSBadgeView 的作者开发的一款轻量级的 AppDelegate 解耦工具。它将 AppDelegate 各个功能点独立出来,并通过代理的方式将控制权下发。
- 将 main.m 中的 AppDelegate 替换成JSDecoupledAppDelegate:
return UIApplicationMain(argc, argv, nil, NSStringFromClass([JSDecoupledAppDelegate class]));
- 指定你需要处理的各个 JSDecoupledAppDelegate 的子 delegate。例如,你需要实现didFinishLaunchingWithOptions 方法,则新建一个类,在其中添加
+ (void)load
{
[JSDecoupledAppDelegate sharedAppDelegate].appStateDelegate = [[self alloc] init];
}
然后就可以在里面实现我们以前在 didFinishLaunchingWithOptions 的方法。
这两种方法各有优缺点,相对来说,我推荐使用第一种方法,实现各模块的AppDelegate拆分。
二、FRDModuleManager独立工程如何接入
1、需要的文件
一般情况下,我们直接copy主工程的AppDelegate即可,因为已经优化完成,不存在多余代码。另外需要建立自己的module,用来实现钩子函数,例如:
@interface YRDPlatformModule()
@end
@implementation YRDPlatformModule
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//自己的初始化等方法
return YES;
}
而上诉的YRDPlatformModule
就是在plist里面需要添加的module名称,这时候,我们就可以一股脑的将自己业务线原本放在AppDelegate的东西放在自己的module里面了。
三、资源文件优化
到这里,我们的工程级别组件化已经基本完车了,但是我们后续基于该工程还有很多的优化项,我们可以不断的拆分细化组件,优化资源文件copy方式,优化编译速度等。
我们下一次将进行资源文件的优化。