App-快速搭建项目框架-AppDelegate入口

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


截屏2021-04-18 下午11.48.23.png

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];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容

  • 严格来讲,AppDelegate除了负责应用生命周期之外,不应该再有多余的责任。 但在iOS 实际开发过程中,很多...
    CoderDancer阅读 3,997评论 7 20
  • 原文链接http://www.cocoachina.com/ios/20161103/17938.html?utm...
    wycandyy阅读 2,324评论 0 22
  • 前言: 之前看了Casa大神的架构设计文章,醍醐灌顶,一直想开个系列文章记录一下(这次就做个小小搬运工,别打脸),...
    M_慕宸阅读 5,673评论 1 13
  • 前言:框架是一个APP的骨骼,核心,一个项目的所有功能以及以后的迭代都是在此基础上进行的,它是开展一个项目的至关重...
    CoderLGL阅读 1,784评论 0 5
  • 架构图: 架构原则:易读性、易维护性、易扩展性。 一、思考 做好一件事,花在思考上的时间应该多于执行。 首先根据产...
    Young_LI阅读 734评论 0 1