BeeHive学习总结

设计原则:

解耦,避免对接口依赖
使用invoke以及动态链接库实现对接口的解耦

BeeHive每个模块都是有生命周期事件的,用来与宿主环境进行必要的交互
事件分为三种类型:

系统事件  
通用事件
业务自定义事件

1.1 系统事件

系统事件通常是Application生命周期事件,例如DidBecomeActive、WillEnterBackground等。
系统事件基本工作流如下:

《BeeHive学习总结》 image

1.2 通用事件

在系统事件的基础之上,扩展了应用的通用事件,例如modSetup、modInit等,可以用于编码实现各插件模块的设置与初始化。

扩展的通用事件如下:

《BeeHive学习总结》 通用事件

1.3 业务自定义事件

如果觉得系统事件、通用事件不足以满足需要,可以通过继承 BHAppdelegate来扩展自己的事件

2. 模块注册

模块注册的方式有静态注册与动态注册两种。

2.1 静态注册

通过在BeeHive.plist文件中注册符合BHModuleProtocol协议模块类:

《BeeHive学习总结》 plist

2.2 动态注册

2.2 动态注册

@implementation HomeModule

BH_EXPORT_MODULE()  // 声明该类为模块入口

@end

在模块入口类实现中 使用BH_EXPORT_MODULE()宏声明该类为模块入口实现类。

2.3 异步加载

如果设置模块导出为BH_EXPORT_MODULE(YES),则会在启动之后第一屏内容展现之前异步执行模块的初始化,可以优化启动时时间消耗

3. 编程开发

BHModuleProtocol为各个模块提供了每个模块可以Hook的函数,用于实现插件逻辑以及代码实现。

3.1 设置环境变量

通过context.env可以判断我们的应用环境状态来决定我们如何配置我们的应用。

-(void)modSetup:(BHContext *)context
{
switch (context.env) {
    case BHEnvironmentDev:
    //....初始化开发环境
    break;
    case BHEnvironmentProd:
    //....初始化生产环境
    default:
    break;
}
}

3.2 模块初始化

如果模块有需要启动时初始化的逻辑,可以在modInit里编写,例如模块注册一个外部模块可以访问的Service接口

-(void)modInit:(BHContext *)context
{
//注册模块的接口服务
[[BeeHive shareInstance] registerService:@protocol(UserTrackServiceProtocol) service:[BHUserTrackViewController class]];
}

3.3 处理系统事件

系统的事件会被传递给每个模块,让每个模块自己决定编写业务处理逻辑,比如3D-Touch功能

-(void)modQuickAction:(BHContext *)context
{
[self process:context.shortcutItem handler:context.scompletionHandler];
}

3.4 模间调用

通过处理Event编写各个业务模块可以实现插件化编程,各业务模块之间没有任何依赖,core与module之间通过event交互,实现了插件隔离。但有时候我们需要模块间的相互调用某些功能来协同完成功能。

通常会有三种形式的接口访问形式:

基于接口的实现Service访问方式(Java spring框架实现)
基于函数调用约定实现的Export Method(PHP的extension,ReactNative的扩展机制)
基于跨应用实现的URL Route模式(iPhone App之间的互访)
我们目前实现了第一种方式,后续会逐步实现后两种方式。

基于接口Service访问的优点是可以编译时检查发现接口的变更,从而及时修正接口问题。缺点是需要依赖接口定义的头文件,通过模块增加得越多,维护接口定义的也有一定工作量。

3.4.1 定义接口

以为HomeServiceProtocol
为例。

@protocol HomeServiceProtocol <NSObject, BHServiceProtocol>- (void)registerViewController:(UIViewController *)vc title:(NSString *)title iconName:(NSString *)iconName;
@end

注册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 调用Service

#import "BHService.h"id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];

3.5 单例与多例

对于有些场景下,我们访问每个声明Service
的对象,希望对象能保留一些状态,那我们需要声明这个Service
对象是一个单例对象。
我们只需要在Service
对象中实现事件函数
声明

-(BOOL) singleton{
 return YES;
}

通过createService
获取的对象则为单例对象,如果实现上面函数返回的是NO
,则createService
返回的是多例。

id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];

3.6 上下文环境Context

初始化设置应用的项目信息,并在各模块间共享整个应用程序的信息

  - (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";//可选,默认为BeeHive.bundle/BeeHive.plist
[BHContext shareInstance].serviceConfigName =  @"BeeHive.bundle/CustomServicePlist";//可选,默认为BeeHive.bundle/BHService.plist
[[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;
} [self.window makeKeyAndVisible]; } return YES;}
    原文作者:Easy_VO
    原文地址: https://www.jianshu.com/p/e76e05e4936d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞