内容简介:关于画了一个结构图,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中进行处理的业务逻辑,比如说我们的 数据库处理
, 分享功能
, 推送功能
等等。
@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; } 复制代码
没看错,这样一搞 AppDelegate
的 application: 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])
就会执行 complete
将 module
和 sel
返回,也就是到了 AppDelegate
里面,继而执行 module
的 sel
函数,并且将参数传递过去。
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
一旦细化,何时销毁也是让开发者头疼的问题。先说这么多,各位看官有任何问题欢迎评论区讨论。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
世界是平的(3.0版)
[美] 托马斯·弗里德曼 / 何帆、肖莹莹、郝正非 / 湖南科学技术出版社 / 2008-9 / 58.00元
世界变得平坦,是不是迫使我们跑得更快才能拥有一席之地? 在《世界是平的》中,托马斯·弗里德曼描述了当代世界发生的重大变化。科技和通信领域如闪电般迅速的进步,使全世界的人们可以空前地彼此接近——在印度和中国创造爆炸式增长的财富;挑战我们中的一些人,比他们更快占领地盘。3.0版新增两章,更新了报告和注释方面的内容,这些内容均采自作者考察世界各地特别是整个美国中心地带的见闻,在美国本土,世界的平坦......一起来看看 《世界是平的(3.0版)》 这本书的介绍吧!