http://www.code4app.com/forum.php?mod=viewthread&tid=11674&extra=page%3D1
https://github.com/alibaba/BeeHive
BeeHive
是用于iOS
的App
模块化编程的框架实现方案,吸收了Spring
框架Service
的理念来实现模块间的API
耦合。
因为基于Spring
的Service
理念,虽然可以使模块间的具体实现与接口解耦,但无法避免对接口类的依赖关系。
为什么不使用invoke
以及动态链接库技术实现对接口实现的解耦,类似Apache
的DSO
的方式?
主要是考虑学习成本难度以及动态调用实现无法在编译检查阶段检测接口参数变更等问题,动态技术需要更高的编程门槛要求。
BeeHive
灵感来源于蜂窝。蜂窝是世界上高度模块化的工程结构,六边形的设计能带来无限扩张的可能。所以我们用了BeeHive
来做为这个项目的命名。
BeeHive
会给每个模块提供生命周期事件,用于与BeeHive
宿主环境进行必要信息交互,感知模块生命周期的变化。
事件分为三种类型:
系统事件通常是Application
生命周期事件,例如DidBecomeActive
、WillEnterBackground
等。
系统事件基本工作流如下:
在系统事件的基础之上,扩展了应用的通用事件,例如modSetup
、modInit
等,可以用于编码实现各插件模块的设置与初始化。
扩展的通用事件如下:
如果觉得系统事件、通用事件不足以满足需要,我们还将事件封装简化成BHAppdelgate
,你可以通过继承 BHAppdelegate
来扩展自己的事件。
模块注册的方式有静态注册与动态注册两种。
通过在BeeHive.plist
文件中注册符合BHModuleProtocol
协议模块类:
@implementation HomeModule
BH_EXPORT_MODULE() // 声明该类为模块入口
@end
在模块入口类实现中 使用BH_EXPORT_MODULE()
宏声明该类为模块入口实现类。
如果设置模块导出为BH_EXPORT_MODULE(YES)
,则会在启动之后第一屏内容展现之前异步执行模块的初始化,可以优化启动时时间消耗。
BHModuleProtocol
为各个模块提供了每个模块可以Hook
的函数,用于实现插件逻辑以及代码实现。
通过context.env
可以判断我们的应用环境状态来决定我们如何配置我们的应用。
-(void)modSetup:(BHContext *)context
{
switch (context.env) {
case BHEnvironmentDev:
//....初始化开发环境
break;
case BHEnvironmentProd:
//....初始化生产环境
default:
break;
}
}
如果模块有需要启动时初始化的逻辑,可以在modInit
里编写,例如模块注册一个外部模块可以访问的Service
接口
-(void)modInit:(BHContext *)context
{
//注册模块的接口服务
[[BeeHive shareInstance] registerService:@protocol(UserTrackServiceProtocol) service:[BHUserTrackViewController class]];
}
系统的事件会被传递给每个模块,让每个模块自己决定编写业务处理逻辑,比如3D-Touch
功能
-(void)modQuickAction:(BHContext *)context
{
[self process:context.shortcutItem handler:context.scompletionHandler];
}
通过处理Event
编写各个业务模块可以实现插件化编程,各业务模块之间没有任何依赖,core
与module
之间通过event
交互,实现了插件隔离。但有时候我们需要模块间的相互调用某些功能来协同完成功能。
通常会有三种形式的接口访问形式:
Service
访问方式(Java spring
框架实现)Export Method
(PHP
的extension
,ReactNatve
的扩展机制)URL Route
模式(iPhone
App
之间的互访)我们目前实现了第一种方式,后续会逐步实现后两种方式。
基于接口Service
访问的优点是可以编译时检查发现接口的变更,从而及时修正接口问题。缺点是需要依赖接口定义的头文件,通过模块增加得越多,维护接口定义的也有一定工作量。
以为HomeServiceProtocol
为例。
@protocol HomeServiceProtocol <NSObject, BHServiceProtocol>
- (void)registerViewController:(UIViewController *)vc title:(NSString *)title iconName:(NSString *)iconName;
@end
Service
有三种方式:
@implementation HomeService
BH_EXPORT_SERVICE()
@end
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>
Service
#import "BHService.h"
id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
对于有些场景下,我们访问每个声明Service
的对象,希望对象能保留一些状态,那我们需要声明这个Service
对象是一个单例对象。
我们只需要在Service
对象中实现事件函数
声明
-(BOOL) singleton
{
return YES;
}
通过createService
获取的对象则为单例对象,如果实现上面函数返回的是NO
,则createService
返回的是多例。
id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
- (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;
}
更多细节可以参考 Example 用例。
cocoapods
pod "BeeHive", '1.0.0'
BeeHive is available under the GPL license. See the LICENSE file for more info.
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.