AppDelegate的模块化+瘦身

栏目: C · 发布时间: 5年前

内容简介:关于画了一个结构图,module1到module4为我们需要在Appdelegate中进行处理的业务逻辑,比如说我们的接口定义了三个函数,

关于 iOS 的模块化,要追溯到16年接触的 BeeHive 了, BeeHive 将功能模块化,以 module 的形式进行构建,以 performSelector: 的形式进行 module 的事件响应,以 protocol 的形式进行module间的通信。可以说思路非常清晰明了了。关于 BeeHive 的代码传送门 alibaba/BeeHive ,star已3.2k,关于BeeHive源码解析可参考霜神文章传送门 BeeHive —— 一个优雅但还在完善中的解耦框架 。实际上我并不认为 BeeHive 可以真正用到我们项目中来,它确实构建了 module ,但是 module实例 带来的内存问题会让人头疼。个人认为将 BeeHive 思想中的 module 部分改造一下用在我们的 AppDelegate 中是完全可行的。下面进入正文。

目录

一、模块拆分

二、模块事件响应

三、模块管理

  • 1.模块注册

  • 2.触发event

  • 3.移除module

四、总结

一、模块拆分

画了一个结构图,module1到module4为我们需要在Appdelegate中进行处理的业务逻辑,比如说我们的 数据库处理分享功能推送功能 等等。

AppDelegate的模块化+瘦身
首先为所有模块定义了三个接口:
@protocol SHRMAppEventModuleProtocol <UIApplicationDelegate>

- (NSInteger)moduleLevel;
- (void)destroyModule;
- (NSString *)moduleID;

@end
复制代码

接口定义了三个函数, moduleLevel 返回module执行的优先级, destroyModule 用来对module进行释放, moduleID 返回当前module的id。接口的默认实现统一在 BaseAppEventModule 中进行。 BaseAppEventModule 为所有module的父类,只有继承了 BaseAppEventModule 的module才能被管理。

关于 BaseAppEventModule 的默认实现也很简单,对module进行销毁的时候用到了 SHRMAppEventModuleManager 下面会讲到,优先级默认设置100.

@interface SHRMBaseAppEventModule : NSObject <SHRMAppEventModuleProtocol>

@end


#define MODULE_LEVEL_DEFAULT 100
@implementation SHRMBaseAppEventModule

- (NSInteger)moduleLevel {
    return MODULE_LEVEL_DEFAULT;
}

- (void)destroyModule {
    [[SHRMAppEventModuleManager sharedInstance] removeModule:[self moduleID]];
    NSLog(@"%@ destroy",NSStringFromClass([self class]));
}

- (NSString *)moduleID {
    return NSStringFromClass([self class]);
}

@end
复制代码

模块的创建上面说到了必须要继承自 SHRMBaseAppEventModule ,只有继承了 SHRMBaseAppEventModule 的module才会被管理,因为只有 SHRMBaseAppEventModule 遵循了 SHRMAppEventModuleProtocol 协议。关于module创建部分:

@interface testMudule : SHRMBaseAppEventModule
@end

@implementation testMudule

- (NSInteger)moduleLevel {
    return 1;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self initMudule];
    [self destroyModule];
    return YES;
}

- (void)initMudule {
    NSLog(@"testMudule init");
}

@end
复制代码

application: didFinishLaunchingWithOptions: 函数的实现展示了一个module的整个生命周期,从创建到销毁的过程,那么 application: didFinishLaunchingWithOptions: 是怎么响应的,实际上module的头文件并没有暴漏任何接口,到这里就实现了功能的 模块化 。那为什么还能执行到这里,这要感谢强大的 runtime 函数 performSelector: ,下面讲一下我对 module 事件响应的处理。

二、模块事件响应

还是以上面的 application: didFinishLaunchingWithOptions: 函数为例,它是怎么来的,很明显这是 AppDelegate 里面的APP生命周期回调:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [[SHRMAppEventModuleManager sharedInstance] handleApplicationEvent:@selector(application:didFinishLaunchingWithOptions:)
                                                              Complete:^(id  _Nonnull module, SEL  _Nonnull sel) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [module performSelector:sel
                     withObject:application
                     withObject:launchOptions];
#pragma clang diagnostic pop
    }];
    return YES;
}
复制代码

没看错,这样一搞 AppDelegateapplication: didFinishLaunchingWithOptions: 就剩这些了,这样一来,所有实现了 application: didFinishLaunchingWithOptions: 的modlue都会被调用,调用优先级根据接口定义的 moduleLevel 返回值确定。到这里我们就完成了AppDelegate 瘦身 的工作,实际上AppDelegate中的其他回调处理是一样的。当然还有一个很重要的没有说,就是 SHRMAppEventModuleManager 做了什么,通过上面的结构图能够看到 SHRMAppEventModuleManager 是个中间件,用来处理module与AppDelegate间的关系。下面说到第三部分,模块管理。

三、模块管理

SHRMAppEventModuleManager 为一个单例,提供了三个接口:

/**
 初始化所有的AppDelegate相关的Event Modules
 */
- (void)registedAllModules;

/**
 触发event module处理AppDelegate回调事件
 
 @param eventSel AppDelegate 回调事件消息
 @param complete module处理handle
 */
- (void)handleApplicationEvent:(SEL)eventSel
                      Complete:(void(^)(id module,SEL sel))complete;

/**
 移除module对象
 
 @param moduleID module ID
 */
- (void)removeModule:(NSString *)moduleID;
复制代码

1.模块注册

模块注册的思路是完全按照 BeeHive 的思想来的,在编译器就将我们的 module 通过 __attribute 函数进行注册。在运行期再将我们注册好的 module 取出来在 registedAllModules 中进行实例化,按照 level 的返回时进行 排序 存储。 __attribute 函数具体做了什么可以参考我之前的文章 写一个易于维护使用方便性能可靠的Hybrid框架(三)—— 配置插件 关于插件注册部分的解释。

2.触发event

handleApplicationEvent:Complete: 为module事件响应的核心函数:

- (void)handleApplicationEvent:(SEL)eventSel
                      Complete:(void(^)(id module,SEL sel))complete {
   
    NSMutableArray *tmpAppEventModules = [[NSMutableArray alloc] initWithArray:self.appEventModules];
    for (id<SHRMAppEventModuleProtocol>module in tmpAppEventModules)
    {
        if ([module conformsToProtocol:@protocol(SHRMAppEventModuleProtocol)])
        {
            if ([module respondsToSelector:eventSel]) {
                if (complete) {
                    complete(module,eventSel);
                }
            }
        }
    }
}
复制代码

if ([module respondsToSelector:eventSel]) 就会执行 completemodulesel 返回,也就是到了 AppDelegate 里面,继而执行 modulesel 函数,并且将参数传递过去。

3.移除module

module 的移除,在 AppDelegate 里面,我们将程序启动之后调用完就不再使用的功能module会手动执行移除操作。这也是前言所说的BeeHive在module移除这一块会稍显复杂,但是在AppDelegate里面,我们是完全可以知道哪些module在加载之后可以立即移除的,另外我们仅在AppDelegate中进行模块化,产生的module实例也会非常少,so,完全没必要担心module所带来的内存开销问题。

- (void)removeModule:(NSString *)moduleID {
    NSInteger index = NSNotFound;
    NSInteger resIndex = 0;
    for (id<SHRMAppEventModuleProtocol>module in self.appEventModules)
    {
        if ([[module moduleID] isEqualToString:moduleID])
        {
            index = resIndex;
            break;
        }
        resIndex++;
    }
    
    if (index != NSNotFound) {
        [self.appEventModules removeObjectAtIndex:index];
    }
}
复制代码

总结

最后总结一下,关于模块化,现在总体来看比较流行,也有很多介绍模块化,组件化具体实施之路的文章,都很优秀,也值得学习。关于解耦,我更倾向于 protocol 的方式,接口 protocol 化,代码易读且清晰。之前看过 mrpeak 在组件化方面的文章,传送门iOS 组件化方案,个人觉得 protocol+version 的方案和 BeeHive 非常像, protocol 解耦, version 进行 module 的版本管理,但是还是没有解决 module 所带来的内存开销问题, module 一旦细化,何时销毁也是让开发者头疼的问题。先说这么多,各位看官有任何问题欢迎评论区讨论。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法设计与分析基础

算法设计与分析基础

Anany Levitin / 潘彦 / 清华大学出版社 / 2015-2-1 / 69.00元

作者基于丰富的教学经验,开发了一套全新的算法分类方法。该分类法站在通用问题求解策略的高度,对现有大多数算法准确分类,从而引领读者沿着一条清晰、一致、连贯的思路来探索算法设计与分析这一迷人领域。《算法设计与分析基础(第3版)》作为第3版,相对前版调整了多个章节的内容和顺序,同时增加了一些算法,并扩展了算法的应用,使得具体算法和通用算法设计技术的对应更加清晰有序;各章累计增加了70道习题,其中包括一些......一起来看看 《算法设计与分析基础》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具