BeeHive
0. 摘要
BeeHive
是 iOS 中的模块化程序实现,它吸收了 Spring Framework 服务API概念,以避免模块之间的直接耦合。
0.1 基本架构
我们可以从这张图片了解 BeeHive 的架构。
0.2 核心概念
- 模块:模块根据不同功能进行分隔,每个模块都可以通过其自身服务与其他模块进行通信。
- 服务:服务是特定模块的接口。
0.3 实现特性
- 操作框架的插件模块开发
- 模块实现与接口调用分离
- 管理模块生命周期,扩展系统事件的适用性
0.4 设计
BeeHive
基于Spring
服务概念,尽管您可以在模块之间实现特定接口的解耦,但无法避免接口类之间的依赖。
为什么不使用调用和动态链接库技术进行解耦,类似于Apache
的DSO
方式呢?
主要是因为实现的学习难度和成本,以及动态调用接口参数在编译时无法检查阶段变化问题,动态编程技术需要更高的门槛要求。
0.5 项目名称由来
BeeHive
受到蜂巢的启发。蜂巢
是世界上高度模块化的工程结构,六角形设计可以带来无限的扩展可能性。因此,我们为这个项目的蜂巢命名。
1. 模块生命周期事件
BeeHive的每个模块都会为宿主环境提供生命周期事件,并且每个模块必须与BeeHive交换必要的信息,以观察生命周期循环中的变化。
事件分为三种类型
- 系统事件
- 通用事件
- 业务自定义事件
1.1 系统事件
系统事件通常是应用程序生命周期事件,例如DidBecomeActive、WillEnterBackground等。系统事件的基本工作流程如下:
1.2 通用事件
基于系统事件的扩展通用应用事件,如modSetup、modInit等,可用于编码每个插件模块的初始化设置。
扩展通用事件如下:
1.3 业务自定义事件
如果您觉得系统事件无法满足通用需求,我们可以将事件打包到BHAppdelgate中,您可以通过继承BHAppdelgate创建自己的事件,同时通过BHContext Lane模块的ByName访问每个模块的入口类,增加触发点。
2. 模块注册
注册模块分为两种类型:静态注册和动态注册。
2.1 静态注册
2.2 动态注册
使用BH_EXPORT_MODULE
宏在类实现中声明模块入口类。
@implementation HomeModule
BH_EXPORT_MODULE(YES)
-(void)modInit:(BHContext *)context;
@end
2.3 异步加载
如果模块设置为导出BH_EXPORT_MODULE(YES),则会在首次屏幕显示内容之后,优化异步执行模块初始化,这样可以减少首屏加载时间消耗
3. 编程
BHModuleProtocol
提供各种模块,每个模块都可以钩函数,以及实现插件代码的逻辑,您可以在 BHModuleProtocol.h
中找到该协议。
3.1 设置环境变量
通过 context.env 我们可以判断应用程序的环境状态,从而决定如何配置我们的应用程序
-(void)modSetup:(BHContext *)context
{
switch (context.env) {
case BHEnvironmentDev:
break;
case BHEnvironmentProd:
default:
break;
}
}
3.2 模块初始化
如果模块需要开始初始化逻辑,可以在准备阶段调用 modInit,例如,模块可以注册外部模块接口以访问服务
-(void)modInit:(BHContext *)context
{
[[BeeHive shareInstance] registerService:@protocol(UserTrackServiceProtocol) service:[BHUserTrackViewController class]];
}
3.3 事件处理系统
事件系统将传递给每个模块,以便每个模块可以决定编写业务逻辑。
-(void)modQuickAction:(BHContext *)context
{
[self process:context.shortcutItem handler:context.scompletionHandler];
}
3.4 交互式模式调用
事件通过处理各种业务模块的插件编程准备,各个业务模块之间没有依赖关系,通过核心模块和事件模块间的交互,实现插件隔离。但有时我们需要在模块之间调用相互的功能,以完成协作。
通常以三种形式来访问服务
- 通过接口(如
Spring
) - 通过
Export Method
(如PHP
/ReactNative
扩展) - 通过
URL Route
模式(如 iPhone 应用之间的交互)
接口类型的服务访问可以发挥编译时检查的优点,如果发现接口发生变化,可以及时纠正接口问题。缺点是必须依赖于模块提供的接口定义头文件,接口定义越多,维护工作量越大。
3.4.1 声明服务接口
以 HomeServiceProtocol 为例
@protocol HomeServiceProtocol <NSObject, BHServiceProtocol>
-(void)registerViewController:(UIViewController *)vc title:(NSString *)title iconName:(NSString *)iconName;
@end
3.4.2 注册服务
注册 ViewController Service 有两种方法。
API 注册
[[BeeHive shareInstance] registerService:@protocol(HomeServiceProtocol) service:[BHViewController class]];
BHService.plist
注册
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>HomeServiceProtocol</key>
<string>BHViewController</string>
</dict>
</plist>
3.4.3 服务调用
#import "BHService.h"
id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
// use homeVc do invocation
3.5 单例或多个实例
在某些场景中,我们访问每个声明为服务对象的对象,希望保留一些状态,那么我们需要声明这个服务对象是单例对象。
我们只需要在事件服务对象中实现功能声明。
-(BOOL) singleton
{
return YES;
}
对象通过createService单例对象获得,如果函数返回上述内容为否,createService返回多种情况。
id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
3.6 全局上下文
初始化应用程序项目信息,并在各个模块之间共享应用程序信息。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[BHContext shareInstance].env = BHEnvironmentDev;
[BHContext shareInstance].application = application;
[BHContext shareInstance].launchOptions = launchOptions;
[BHContext shareInstance].moduleConfigName = @"BeeHive.bundle/CustomModulePlist";
[BHContext shareInstance].serviceConfigName = @"BeeHive.bundle/CustomServicePlist";
[BHContext shareInstance].appkey = xxxxxx;
[BHContext shareInstance].Mtopkey = xxxxx;
[[BeeHive shareInstance] setContext:[BHContext shareInstance]];
[super application:application didFinishLaunchingWithOptions:launchOptions];
id<HomeServiceProtocol> homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
if ([homeVc isKindOfClass:[UIViewController class]]) {
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:(UIViewController*)homeVc];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = navCtrl;
[self.window makeKeyAndVisible];
}
return YES;
}
4. 集成
cocoapods
pod "BeeHive", '1.1.1'
5. 作者
6. 微信群
由于微信群人数已达到上限,您可以通过搜索“dolphinux”加入我们。
7. 许可证
BeeHive 按照GPL许可证提供。有关更多信息,请参阅LICENSE文件。