AppDelegate组件化
AppDelegate瘦身
- AppDelegate是App的入口,对于开发耦合性来说,AppDelegate除了负责应用生命周期之外,尽量不要有大量的代码。
- 但是在iOS 实际开发过程中,很多人习惯将全局变量定义在 AppDelegate 中,会导入比如推送、统计、分享、三方登陆、地图等组件,但如此这般,AppDelegate就变得更加臃肿。在大型项目中,想要解除耦合和模块化时,都不利于AppDelegate的维护。
- 将很多全局变量放在AppDelegate上,将AppDelegate作为一个依赖中心点,虽然很多模块可以访问全局变量,但会产生相互依赖,不利于模块化开发;
- 不同的模块,会根据需要在AppDelegate的不同生命周期方法中,调用各种方法。比如在程序启动时在application:didFinishLaunchingWithOptions:内注册一个初始化方法;
组件化分开引入
创建继承NSObject的AppModuleManager单利类
AppModuleManager.h文件
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@import UIKit;
@import UserNotifications;
@protocol AppModuleManagerDelegate <UIApplicationDelegate, UNUserNotificationCenterDelegate>
@end
@interface AppModuleManager : NSObject<UIApplicationDelegate, UNUserNotificationCenterDelegate>
+ (instancetype)sharedInstance;
- (void)loadModulesWithPlistFile:(NSString *)plistFile;
- (NSArray<id<AppModuleManagerDelegate>> *)allModules;
@end
NS_ASSUME_NONNULL_END
AppModuleManager.m文件
#import "AppModuleManager.h"
@interface AppModuleManager ()
@property (nonatomic, strong) NSMutableArray<id<AppModuleManagerDelegate>> *modules;
@end
@implementation AppModuleManager
+ (instancetype)sharedInstance
{
static AppModuleManager *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
});
return instance;
}
- (NSMutableArray<id<AppModuleManagerDelegate>> *)modules
{
if (!_modules) {
_modules = [NSMutableArray array];
}
return _modules;
}
- (void)addModule:(id<AppModuleManagerDelegate>) module
{
if (![self.modules containsObject:module]) {
[self.modules addObject:module];
}
}
- (void)loadModulesWithPlistFile:(NSString *)plistFile
{
NSArray<NSString *> *moduleNames = [NSArray arrayWithContentsOfFile:plistFile];
for (NSString *moduleName in moduleNames) {
id<AppModuleManagerDelegate> module = [[NSClassFromString(moduleName) alloc] init];
[self addModule:module];
}
}
- (NSArray<id<AppModuleManagerDelegate>> *)allModules
{
return self.modules;
}
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module applicationDidFinishLaunching:application];
}
}
}
#pragma mark - State Transitions / Launch time:
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application willFinishLaunchingWithOptions:launchOptions];
}
}
return YES;
}
#pragma mark - 程序第一次加载完毕,就会调用此方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didFinishLaunchingWithOptions:launchOptions];
}
}
return YES;
}
#pragma mark - 程序将要失去焦点 - 不能交互
- (void)applicationWillResignActive:(UIApplication *)application
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module applicationWillResignActive:application];
}
}
}
#pragma mark - 程序已经进入后台,通常我们会在这个时候保存数据
- (void)applicationDidEnterBackground:(UIApplication *)application
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module applicationDidEnterBackground:application];
}
}
}
#pragma mark - 程序将要进入前台,通常我们会在这个时候恢复数据
- (void)applicationWillEnterForeground:(UIApplication *)application
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module applicationWillEnterForeground:application];
}
}
}
#pragma mark - 程序已经获取焦点 - 可以交互
- (void)applicationDidBecomeActive:(UIApplication *)application
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module applicationDidBecomeActive:application];
}
}
}
#pragma mark - 程序挂了,将要完全退出。
- (void)applicationWillTerminate:(UIApplication *)application
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module applicationWillTerminate:application];
}
}
}
#pragma mark - 程序接收到内存警告
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module applicationDidReceiveMemoryWarning:application];
}
}
}
#pragma mark - 程序接收到url处理
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
for (id<AppModuleManagerDelegate> module in self.modules) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if ([module respondsToSelector:_cmd]) {
return [module application:application handleOpenURL:url];
}
#pragma clang diagnostic pop
}
return YES;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation
{
for (id<AppModuleManagerDelegate> module in self.modules) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if ([module respondsToSelector:_cmd]) {
return [module application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
}
#pragma clang diagnostic pop
}
return YES;
}
#pragma clang diagnostic pop
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options API_AVAILABLE(ios(9.0))
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
return [module application:app openURL:url options:options];
}
}
return YES;
}
#pragma mark - Handling Remote Notification
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
}
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didFailToRegisterForRemoteNotificationsWithError:error];
}
}
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
}
}
#pragma mark - Handling Local Notification
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didReceiveRemoteNotification:userInfo];
}
}
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)(void))completionHandler
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application handleActionWithIdentifier:identifier forRemoteNotification:userInfo completionHandler:completionHandler];
}
}
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)(void))completionHandler
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application handleActionWithIdentifier:identifier forRemoteNotification:userInfo withResponseInfo:responseInfo completionHandler:completionHandler];
}
}
}
#pragma mark - Handling Local Notification
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
API_AVAILABLE(ios(10.0)){
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module userNotificationCenter:center willPresentNotification:notification withCompletionHandler:completionHandler];
}
}
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
API_AVAILABLE(ios(10.0)){
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
}
}
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didReceiveLocalNotification:notification];
}
}
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)(void))completionHandler
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application handleActionWithIdentifier:identifier forLocalNotification:notification completionHandler:completionHandler];
}
}
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)(void))completionHandler
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:responseInfo completionHandler:completionHandler];
}
}
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didRegisterUserNotificationSettings:notificationSettings];
}
}
}
#pragma mark - Handling Continuing User Activity and Handling Quick Actions
- (BOOL)application:(UIApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType
{
BOOL result = NO;
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
result = result || [module application:application willContinueUserActivityWithType:userActivityType];
}
}
return result;
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
BOOL result = NO;
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
result = result || [module application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}
}
return result;
}
- (void)application:(UIApplication *)application didUpdateUserActivity:(NSUserActivity *)userActivity
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didUpdateUserActivity:userActivity];
}
}
}
- (void)application:(UIApplication *)application didFailToContinueUserActivityWithType:(NSString *)userActivityType error:(NSError *)error
{
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application didFailToContinueUserActivityWithType:userActivityType error:error];
}
}
}
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler
API_AVAILABLE(ios(9.0)){
for (id<AppModuleManagerDelegate> module in self.modules) {
if ([module respondsToSelector:_cmd]) {
[module application:application performActionForShortcutItem:shortcutItem completionHandler:completionHandler];
}
}
}
@end
// AppModulesRegister.plist
AppDelegate.m中实现
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"AppModulesRegister" ofType:@"plist"];
AppModuleManager *manager = [AppModuleManager sharedInstance];
[manager loadModulesWithPlistFile:plistPath];
[manager application:application willFinishLaunchingWithOptions:launchOptions];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UIApplication sharedApplication].statusBarHidden = NO;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
[[AppModuleManager sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
在需要的方法实现
AppModulePush.h文件
#import <Foundation/Foundation.h>
#import "AppModuleManager.h"
NS_ASSUME_NONNULL_BEGIN
@interface AppModulePush : NSObject<AppModuleManagerDelegate>
@end
NS_ASSUME_NONNULL_END
AppModulePush.m文件
#pragma mark - 程序将要失去焦点 - 不能交互
- (void)applicationWillResignActive:(UIApplication*)application
{
[[AppModuleManager sharedInstance] applicationWillResignActive:application];
}
#pragma mark - 程序已经进入后台,通常我们会在这个时候保存数据
- (void)applicationDidEnterBackground:(UIApplication*)application
{
[[AppModuleManager sharedInstance] applicationDidEnterBackground:application];
}
#pragma mark - 程序将要进入前台,通常我们会在这个时候恢复数据
- (void)applicationWillEnterForeground:(UIApplication*)application
{
[[AppModuleManager sharedInstance] applicationWillEnterForeground:application];
}
#pragma mark - 程序已经获取焦点 - 可以交互
- (void)applicationDidBecomeActive:(UIApplication*)application
{
[[AppModuleManager sharedInstance] applicationDidBecomeActive:application];
}
#pragma mark - 程序挂了,将要完全退出。
- (void)applicationWillTerminate:(UIApplication*)application
{
[[AppModuleManager sharedInstance] applicationWillTerminate:application];
}
#pragma mark - 程序接收到内存警告
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
[[AppModuleManager sharedInstance] applicationDidReceiveMemoryWarning:application];
}