iOS 模塊化編程框架 BeeHive

github下載地址:https://github.com/alibaba/BeeHive

BeeHive 詳細(xì)介紹

BeeHive是用于iOS的app模塊化編程的框架實(shí)現(xiàn)方案,吸收了Spring框架service的理念來實(shí)現(xiàn)模塊間的API耦合?;驹砣缦?

基本原理.jpg

實(shí)現(xiàn)以下特性

  • 插件化的模塊開發(fā)運(yùn)行框架
  • 模塊具體實(shí)現(xiàn)與接口調(diào)用分離
  • 模塊生命周期管理,擴(kuò)展了應(yīng)用的系統(tǒng)事件

因?yàn)榛赟pring的Service理念,雖然可以使模塊間的具體實(shí)現(xiàn)與接口解耦,但無法避免對(duì)接口類的依賴關(guān)系。

為什么不使用invoke以及動(dòng)態(tài)鏈接庫技術(shù)實(shí)現(xiàn)對(duì)接口實(shí)現(xiàn)的解耦,類似Apache的DSO的方式。

主要是考慮學(xué)習(xí)成本難度以及動(dòng)態(tài)調(diào)用實(shí)現(xiàn)無法在編譯檢查階段檢測(cè)接口參數(shù)變更等問題,動(dòng)態(tài)技術(shù)需要更高的編程門檻要求

BeeHive靈感來源于蜂窩。蜂窩是世界上高度模塊化的工程結(jié)構(gòu),六邊形的設(shè)計(jì)能帶來無限擴(kuò)張的可能。所以我們用了BeeHive來做為這個(gè)項(xiàng)目的命名。

生命周期的變化

事件

BeeHive會(huì)給每個(gè)模塊提供生命周期事件,用于與BeeHive宿主環(huán)境進(jìn)行必要信息交互 事件分為三種類型:

  • 系統(tǒng)事件
  • 通用事件
  • 業(yè)務(wù)自定義事件

系統(tǒng)事件

系統(tǒng)事件通常是Application生命周期事件,例如DidBecomeActive、WillEnterBackground等系統(tǒng)事件基本工作流如下:


系統(tǒng)事件基本工作流.jpeg

通用事件

在系統(tǒng)事件的基礎(chǔ)之上,擴(kuò)展了應(yīng)用的通用事件,例如modSetup、modInit等,可以用于編碼實(shí)現(xiàn)各插件模塊的設(shè)置與初始化

擴(kuò)展的通用事件如下:


通用事件.jpeg

業(yè)務(wù)自定義事件

如果覺得系統(tǒng)事件、通用事件不足以滿足需要,我們還將事件封裝簡化成BHAppdelgate,你可以通過繼承BHAppdelegate來擴(kuò)展自己的事件。

注冊(cè)

模塊注冊(cè)的方式有靜態(tài)注冊(cè)與動(dòng)態(tài)注冊(cè)兩種

  • 靜態(tài)注冊(cè)
    通過在BeeHive.plist文件中注冊(cè)符合BHModuleProtocol協(xié)議模塊類


    靜態(tài)注冊(cè).png
  • 動(dòng)態(tài)注冊(cè)
@implementation HomeModule
BH_EXPORT_MODULE()  //聲明該類為模塊入口

在模塊入口類實(shí)現(xiàn)中 使用BH_EXPORT_MODULE()宏聲明該類為模塊入口實(shí)現(xiàn)類

異步加載

如果設(shè)置模塊導(dǎo)出為BH_EXPORT_MODULE(YES),則會(huì)在啟動(dòng)之后第一屏內(nèi)容展現(xiàn)之前異步執(zhí)行模塊的初始化,可以優(yōu)化啟動(dòng)時(shí)時(shí)間消耗

編程開發(fā)

BHModuleProtocol為各個(gè)模塊提供了每個(gè)模塊可以hook的函數(shù),用于實(shí)現(xiàn)插件邏輯以及代碼實(shí)現(xiàn)

  • 設(shè)置環(huán)境變量
    通過context.env可以判斷我們的應(yīng)用環(huán)境狀態(tài)來決定我們?nèi)绾闻渲梦覀兊膽?yīng)用
-(void)modSetup:(BHContext *)context
{
    switch (context.env) {
        case BHEnvironmentDev:
        //....初始化開發(fā)環(huán)境
        break;
        case BHEnvironmentProd:
        //....初始化生產(chǎn)環(huán)境
        default:
        break;
    }
}
  • 模塊初始化
    如果模塊有需要啟動(dòng)時(shí)初始化的邏輯,可以在modInit里編寫,例如模塊注冊(cè)一個(gè)外部模塊可以訪問的Service接口
-(void)modInit:(BHContext *)context
{
    //注冊(cè)模塊的接口服務(wù)
    [[BeeHive shareInstance] registerService:@protocol(UserTrackServiceProtocol) service:[BHUserTrackViewController class]];
}
  • 處理系統(tǒng)事件
    系統(tǒng)的事件會(huì)被傳遞給每個(gè)模塊,讓每個(gè)模塊自己決定編寫業(yè)務(wù)處理邏輯,比如3D-Touch功能
-(void)modQuickAction:(BHContext *)context
{
    [self process:context.shortcutItem handler:context.scompletionHandler];
}

模間調(diào)用

通過處理Event編寫各個(gè)業(yè)務(wù)模塊可以實(shí)現(xiàn)插件化編程,各業(yè)務(wù)模塊之間沒有任何依賴,core與module之間通過event交互,實(shí)現(xiàn)了插件隔離。但有時(shí)候我們需要模塊間的相互調(diào)用某些功能來協(xié)同完成功能。 通常會(huì)有三種形式的接口訪問形式

  • 基于接口的實(shí)現(xiàn)Service訪問方式(java spring框架實(shí)現(xiàn))
  • 基于函數(shù)調(diào)用約定實(shí)現(xiàn)的Export Method(PHP的extension,ReactNatve的擴(kuò)展機(jī)制)
  • 基于跨應(yīng)用實(shí)現(xiàn)的Url route模式(iphone app之間的互訪)

我們目前實(shí)現(xiàn)了第一種方式,后續(xù)會(huì)逐步實(shí)現(xiàn)后兩種方式

Servcie訪問

Service訪問的優(yōu)點(diǎn)是可以編譯時(shí)檢查發(fā)現(xiàn)接口的變更,從而及時(shí)修正接口問題。缺點(diǎn)是需要依賴接口定義的頭文件,通過模塊增加得越多,維護(hù)接口定義的也有一定工作量。以為HomeServiceProtocol為例

  • 定義HomeServiceProtocol暴露模塊對(duì)外訪問的接口
@protocol HomeServiceProtocol <NSObject, BHServiceProtocol>
-(void)registerViewController:(UIViewController *)vc title:(NSString *)title iconName:(NSString *)iconName;
@end
  • 注冊(cè)Service有三種方式
  • 聲明式注冊(cè)
@implementation HomeService
BH_EXPORT_SERVICE()
  • API注冊(cè)
[[BeeHive shareInstance] registerService:@protocol(HomeServiceProtocol) service:[BHViewController class]];
  • BHService.plist注冊(cè)
<?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>
  • 調(diào)用
#import "BHService.h"
id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];

單例與多例

對(duì)于有些場(chǎng)景下,我們?cè)L問每個(gè)聲明為service的對(duì)象,希望對(duì)象能保留一些狀態(tài),那我們需要聲明這個(gè)service對(duì)象是一個(gè)單例對(duì)象。

我們只需要在service對(duì)象中實(shí)現(xiàn)事件函數(shù)

聲明

-(BOOL) singleton
{
    return YES;
}

通過createService獲取的對(duì)象則為單例對(duì)象,如果實(shí)現(xiàn)上面函數(shù)返回的是NO,則createService返回的是多例

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

上下文環(huán)境Context

  • 初始化設(shè)置應(yīng)用的項(xiàng)目信息,并在各模塊間共享整個(gè)應(yīng)用程序的信息
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [BHContext shareInstance].env = BHEnvironmentDev; //定義應(yīng)用的運(yùn)行開發(fā)環(huán)境
    [BHContext shareInstance].application = application;
    [BHContext shareInstance].launchOptions = launchOptions;
    [BHContext shareInstance].moduleConfigName = @"BeeHive.bundle/CustomModulePlist";//可選,默認(rèn)為BeeHive.bundle/BeeHive.plist
    [BHContext shareInstance].serviceConfigName =  @"BeeHive.bundle/CustomServicePlist";//可選,默認(rèn)為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;
}

更多細(xì)節(jié)可以參考Example用例

  • 集成方式

use cocoapods
pod "BeeHive", '1.0.0'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容