美文网首页iOS优化
AppDelegate如何瘦身

AppDelegate如何瘦身

作者: sun5kong | 来源:发表于2019-07-14 17:01 被阅读0次
// 友盟统计

// JPush

// 分享相关

// 基础数据

// 数据库

// 等等...

无穷无尽的需求堆在Appdelegate中将会不忍直视.

1. 各组件分开引入

关于组件的拆分,就根据具体项目进行拆分,假如APP被拆分了AModule、BModule、CModule,那么,应该如何引入这些组件呢?你可能会想到APP的入口AppDelegate。在平时开发中,AppDelegate中往往初始化了好多组件,比如推送、统计等组件,这样就会导致AppDelegate的臃肿。

所以,我们可以增加一个ModuleManager ,专门用来初始化各组件。

首先增加一个 ModuleProtocol:

#import <Foundation/Foundation.h>
@import UIKit;
@import UserNotifications;

@protocol ModuleProtocol <UIApplicationDelegate, UNUserNotificationCenterDelegate>

@end

我们在ModuleManager中hook住UIApplicationDelegateUNUserNotificationCenterDelegate中的方法,使相应的组件中实现了对应方法,在相应时机就会调用组建里的对应方法:

#import "ModuleManager.h"
#import "AppDelegate.h"
#import <objc/runtime.h>

#define ALL_MODULE [[ModuleManager sharedInstance] allModules]
#define SWIZZLE_METHOD(m) swizzleMethod(class, @selector(m),@selector(module_##m));

@interface ModuleManager ()

@property (nonatomic, strong) NSMutableArray<id<ModuleProtocol>> *modules;

@end

@implementation ModuleManager

+ (instancetype)sharedInstance {
    static ModuleManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[ModuleManager alloc] init];
    });
    return instance;
}

- (void)loadModulesWithPlistFile:(NSString *)plistFile {
    NSArray *modules = [NSArray arrayWithContentsOfFile:plistFile];
    NSLog(@"%@", modules);
    for (NSString *moduleName in modules) {
        [self addModule:moduleName];
    }
}

- (void)addModule:(NSString *)moduleName {
    Class class = NSClassFromString(moduleName);
    if (class_conformsToProtocol(class, @protocol(ModuleProtocol))) {
        id<ModuleProtocol> module = [[class alloc] init];
        [self.modules addObject:module];
    }
}

- (NSMutableArray<id<ModuleProtocol>> *)modules {
    if (!_modules) {
        _modules = [[NSMutableArray alloc] init];
    }
    return _modules;
}
- (NSArray<id<ModuleProtocol>> *)allModules {
    return self.modules;
}
@end

@implementation AppDelegate (Module)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        SWIZZLE_METHOD(application:willFinishLaunchingWithOptions:);
        SWIZZLE_METHOD(application:didFinishLaunchingWithOptions:);
        ......
    });
}

static inline void swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector) {
    // the method might not exist in the class, but in its superclass
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    
    // class_addMethod will fail if original method already exists
    BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    
    // the method doesn’t exist and we just added one
    if (didAddMethod) {
        class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    }
    else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}


- (BOOL)module_application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    BOOL result = [self module_application:application willFinishLaunchingWithOptions:launchOptions];
    for (id<ModuleProtocol> module in ALL_MODULE) {
        if ([module respondsToSelector:_cmd]) {
            [module application:application willFinishLaunchingWithOptions:launchOptions];
        }
    }
    return result;
}

- (BOOL)module_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    BOOL result = [self module_application:application didFinishLaunchingWithOptions:launchOptions];
    for (id<ModuleProtocol> module in ALL_MODULE) {
        if ([module respondsToSelector:_cmd]) {
            [module application:application didFinishLaunchingWithOptions:launchOptions];
        }
    }
    return result;
}
......

@end

ModuleManager.h:

#import <Foundation/Foundation.h>
#import "ModuleProtocol.h"

@interface ModuleManager : NSObject

+ (instancetype)sharedInstance;

- (void)loadModulesWithPlistFile:(NSString *)plistFile;

- (NSArray<id<ModuleProtocol>> *)allModules;

@end

之后我们通过一个 ModulesRegister.plist文件管理需要引入的组件:


如上图,假如我们要引入AModule、BModule、CModule,那么这三个Module只需要实现协议ModuleProtocol,然后实现AppDelegate中对应的方法,在对应方法中初始化自身即可:
AModule.h:

#import <Foundation/Foundation.h>
#import "ModuleProtocol.h"

@interface AModule : NSObject<ModuleProtocol>

@end

AModule.m:

#import "AModule.h"

@implementation AModule

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    //初始化AModule
    return YES;
}
@end

之后在AppDelegateload方法中通过ModulesRegister.plist引入各组件即可:

@implementation AppDelegate

+ (void)load {
    //load modules
    NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"ModulesRegister" ofType:@"plist"];
    [[ModuleManager sharedInstance] loadModulesWithPlistFile:plistPath];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ......
}
@end

这样,各组件的开发者在自己的组件中初始化自己,其他人需要使用时只需要加入ModulesRegister.plist文件中即可。

相关文章

  • AppDelegate如何瘦身?

    1、使用分类,拆分模块到分类中。(分类中同名方法覆盖问题)2、不使用分类,拆分模块,每个模块的处理数据方法注册到原...

  • AppDelegate如何瘦身

    无穷无尽的需求堆在Appdelegate中将会不忍直视. 1. 各组件分开引入 关于组件的拆分,就根据具体项目进行...

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

    AppDelegate组件化 AppDelegate瘦身 AppDelegate是App的入口,对于开发耦合性来说...

  • AppDelegate瘦身

    简介 看到这个话题,自然是想整理AppDelegate里面各自杂乱的逻辑。 目标 各个模块可以单独实现,不需要在A...

  • 问题集 实战部分

    实战部分 1: AppDelegate如何瘦身? 一类注重于分发,比如 FRDModuleManager 和 JS...

  • 如何给你的AppDelegate瘦身

    上篇如何把业务逻辑从ViewController中拆分出来讲了给ViewController瘦身,这篇继续讲给Ap...

  • iOS AppDelegate瘦身

    个人建议 AppDelegate该文件中只处理app的delegate的事件,不进行其他代码的编写,已达到简洁明晰...

  • AppDelegate的瘦身

    问题:AppDelegate里面各种各样的sdk的集成 1.初始化控制器2.初始化分享3.初始化推送等 这么多的东...

  • AppDelegate瘦身摸索

    新年第一个项目,没想到又加急了一个项目,一周要完成70%。。。。。这不明摆着要加班的节奏吗???还好,项目中的模块...

  • iOS组件化(二)模块生命周期独立化

    虽然我们重构了AppDelegate,给AppDelegate瘦身,但是还是会有各模块耦合在一起的情况。所以,组件...

网友评论

    本文标题:AppDelegate如何瘦身

    本文链接:https://www.haomeiwen.com/subject/jgcikctx.html