{"id":26214461,"url":"https://github.com/ljunb/componentbus","last_synced_at":"2025-10-09T08:40:03.544Z","repository":{"id":92176757,"uuid":"402494198","full_name":"ljunb/ComponentBus","owner":"ljunb","description":"一种组件化通信方式","archived":false,"fork":false,"pushed_at":"2021-09-22T10:07:17.000Z","size":316,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"feature/1.0.0","last_synced_at":"2025-10-09T08:40:00.588Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ljunb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-09-02T16:44:22.000Z","updated_at":"2021-09-24T01:57:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"21daf1f2-274e-4da9-9e60-085fb5eb488b","html_url":"https://github.com/ljunb/ComponentBus","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ljunb/ComponentBus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ljunb%2FComponentBus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ljunb%2FComponentBus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ljunb%2FComponentBus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ljunb%2FComponentBus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ljunb","download_url":"https://codeload.github.com/ljunb/ComponentBus/tar.gz/refs/heads/feature/1.0.0","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ljunb%2FComponentBus/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001050,"owners_count":26082991,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-12T10:17:01.785Z","updated_at":"2025-10-09T08:40:03.539Z","avatar_url":"https://github.com/ljunb.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 目录\n- [简介](#CBus简介)\n    - [核心功能](#核心功能)\n    - [优势](#优势)\n- [快速开始](#快速开始)\n    - [封装CBus组件](#封装CBus组件)\n    - [调用CBus组件](#调用CBus组件)\n- [CBusAPIs](#CBusAPIs)   \n    - [CBus](#CBus)\n    - [CBus(LifeCycle)](#CBus(LifeCycle))  \n    - [CBus(Register)](#CBus(Register))  \n    - [CBusComponent](#CBusComponent)\n    - [CBusClient](#CBusClient)\n    - [CBusRequest](#CBusRequest)\n    - [CBusResponse](#CBusResponse)\n    - [CBusDispatcher](#CBusDispatcher)\n    - [CBusInterceptor](#CBusInterceptor)\n\n## CBus简介\n- 一种组件化框架\n- 将某个模块对外方法使用CBus包装，那么就形成了一个CBus组件\n- CBus对外暴露组件名称以及各种组件方法\n- CBus封装了组件之间的底层数据通信逻辑，组件与组件之前没有接口依赖\n- 更多其他特性\n\n### 核心功能\n\n- 组件注册表\n    - main函数执行之前，所有组件自动注册到一个Map，形成组件注册表\n    - 后续组件调用，统一来注册表查找组件\n- 组件方法转发    \n    - 注册表中通过组件名称找到组件对象\n    - 在组件对象中查找对应的组件方法并调用之\n    - 框架层相当于模块与模块之间的胶水层，解除了模块接口依赖\n- 组件方法调度\n    - 允许调用方同步/异步方式调用其他组件方法\n    - 框架内部维护了一个NSOperationQueue，用于执行异步调用逻辑\n    - 不用关心其他组件方法是同步或者异步实现\n- 生命周期管理\n    - 在AppDelegate中进行生命周期方法绑定\n- 拦截器\n    - 允许开发者自定义拦截器，实现AOP编程\n    \n### 优势\nCBus消除了每个组件之间的依赖关系，可彻底解耦业务依赖。\n\n## 快速开始\n### 封装CBus组件\n快速封装一个业务组件：\n```objc\n#import \"HomeComponent.h\"\n#import \u003cCBus/CBusComponent.h\u003e\n#import \u003cCBus/CBus.h\u003e\n\n// 实现CBusComponent协议\n@interface HomeComponent ()\u003cCBusComponent\u003e\n@end\n\n@implementation HomeComponent\n\n// 注册组件，设置组件名称为：home\nCBUS_COMPONENT(home)\n\n// 标记一个方法\nCBUS_ACTION(testAction) {\n    CBusResponse *res = [CBusResponse success:@{@\"status\": @\"success\", @\"message\": @\"this is a message from test action\"}];\n    // 返回调用结果\n    [cbus finished:res];\n}\n```\n以上示例通过 `CBUS_COMPONENT` 注册了一个 `home` 组件，同时用 `CBUS_ACTION` 标记了一个可供外部调用的组件方法。\n\n### 调用CBus组件\n同步调用：\n```objc\n#import \u003cCBus/CBus.h\u003e\n\n- (void)syncAction {\n    CBus *cbus = [CBus callRequestWithComponent:@\"home\" action:@\"testAction\" params:@{@\"name\": @\"cbus\"}];\n    if (cbus.response.success) {\n        NSLog(@\"CBus response: %@\", cbus.response);\n    }\n}\n```\n\n异步调用：\n```objc\n#import \u003cCBus/CBus.h\u003e\n\n- (void)asyncAction {\n    [CBus asyncCallRequestWithComponent:@\"home\" action:@\"asyncAction\" params:nil complete:^(CBus * _Nonnull cbus) {\n        if (cbus.response.success) {\n            NSLog(@\"CBus response: %@\", cbus.response);\n        }\n    }];\n}\n```\n\n## CBusAPIs\n### CBus\n#### client\n`@property (nonatomic, strong, readonly) CBusClient *client;`\n\nCBus内部维护一个默认的 CBusClient 对象，如无设置，则返回该对象。\n\n#### + setCBusClient:\n`+ (void)setCBusClient:(CBusClient *)client;`\n\n设置 CBusClient 对象。一般情况下，不需要设置，因为内部有默认的 CBusClient 对象。对于一些非常重要的业务或者组件，可以单独设置 CBusClient 对象，\n保证这些组件或者业务在发起组件调用的时候，能够使用单独的操作队列。\n\n#### request\n`@property (nonatomic, strong, readonly) CBusRequest *request;`\n\n每次发起一个调用请求，都会新建 CBusRequest 对象，同时返回一个新的 CBus 对象。`request` 即是当前调用的请求实例。\n\n#### 发起CBusRequest\nCBus 提供了一系列创建 CBusRequest 的快捷方法：\n- 同步调用\n    - `+ (CBus *)callRequestWithComponent:action:`\n    - `+ (CBus *)callRequestWithComponent:action:params:`\n    - `+ (CBus *)callRequestWithComponent:action:params:timeout:`\n- 异步调用\n    - `+ (void)asyncCallRequestWithComponent:action:`\n    - `+ (void)asyncCallRequestWithComponent:action:params:`\n    - `+ (void)asyncCallRequestWithComponent:action:params:complete:`\n    - `+ (void)asyncCallRequestWithComponent:action:params:timeout:complete:`\n    - `+ (void)asyncCallRequestWithComponent:action:params:completeOnMainThread:`\n    - `+ (void)asyncCallRequestWithComponent:action:params:timeout:completeOnMainThread:`\n\n这些方法，实际内部都会生成一个 CBusRequest 对象，其实质是调用了 CBus 的另外两个方法：\n- `+ (CBus *)execute:(CBusRequest *)request;`\n- `+ (void)enqueue:(CBusRequest *)request complete:(CBusAsyncCallCompletion)complete;`\n\n#### response\n`@property (nonatomic, strong, readonly) CBusResponse *response;`\n\n当前调用的响应结果。\n\n#### - finished:\n`- (void)finished:(CBusResponse *)response;`\n\n设置调用结果。前面看到，每个 `CBUS_ACTION` 标识的组件方法，需要给当前组件调用返回调用结果，那么通过该方法进行设置。\n假设组件方法为同步实现，那么在组件方法里面返回结果：\n```objc\nCBUS_ACTION(syncAction) {\n    CBusResponse *res = [CBusResponse success:@{@\"status\": @\"success\", @\"message\": @\"this is a message from test action\"}];\n    // 返回调用结果\n    [cbus finished:res];\n}\n```\n假设组件方法为异步实现，那么在异步回调里面返回结果：\n```objc\nCBUS_ACTION(asyncAction) {\n    dispatch_async(dispatch_get_global_queue(0, 0), ^{\n        [NSThread sleepForTimeInterval:3];\n        \n        CBusResponse *res = [CBusResponse success:@{@\"status\": @\"success\"}];\n        // 返回调用结果\n        [cbus finished:res];\n    });\n}\n```\n\u003e 不论组件实现是同步或者异步，都需要通过 `finised:` 来返回调用结果。\n\n#### @property (readonly) BOOL isFinished;\n当前调用是否已经结束。\n\n#### @property (readonly) BOOL isCanceled;\n当前调用是否已经取消。\n\n#### - cancel\n`- (void)cancel;`\n取消当前组件调用。\n\n### CBus(LifeCycle)\n组件与App生命周期方法绑定处理。\n#### + callAppDelegateActionForSelector:arguments:\n`+ (BOOL)callAppDelegateActionForSelector:(SEL)aSelector arguments:(NSArray *)arguments;`\n\n参考自 [Bifrost生命周期处理](https://github.com/youzan/Bifrost/blob/a1af5b0ecb5909d289a8e4641ccf3c8b23b175fe/Bifrost/Lib/Bifrost.m#L206) 。\n\n### CBus(Register)\n动态组件注册相关。\n#### + registerDynamicComponentForClass:\n`+ (void)registerDynamicComponentForClass:(Class)componentClass;`\n\n根据类型注册一个动态组件。\n\n#### + registerDynamicComponentForName:cls:\n`+ (void)registerDynamicComponentForName:(NSString *)componentName cls:(Class)componentClass;`\n\n给定名称和类型注册一个动态组件。\n\n#### + unregisterDynamicComponentForClass:\n`+ (void)unregisterDynamicComponentForClass:(Class)componentClass;`\n\n根据类型取消注册一个动态组件。\n\n#### + unregisterDynamicComponentForName:\n`+ (void)unregisterDynamicComponentForName:(NSString *)componentName;`\n\n根据名称取消注册一个动态组件。\n\n\n### CBusComponent\nCBusComponent 是组件化协议，每个需要进行组件化的模块都需要实现该协议。\n#### CBUS_COMPONENT\n`CBUS_COMPONENT(name)`\n\n使用该宏进行静态组件的注册，其定义为：\n```objc\n#define CBUS_COMPONENT(name) \\\nCBUS_EXTERN void CBusResigterComponent(Class); \\\n+ (NSString *)componentName { return @#name; } \\\n+ (void)load { CBusResigterComponent(self); }\n```\n因此 App 会在执行 `main` 函数之前，进行组件的注册。对于静态组件，注册的时候会新建一个空实例，并添加至注册表。如果业务方提供了 `name`，那么将作为组件\n的名称添加到注册表中，用于后续的组件调用。如果没有提供 `name`，组件类型将作为其注册表的 `key`。\n\n#### CBUS_DYNAMIC_COMPONENT\n`CBUS_DYNAMIC_COMPONENT(name)`\n使用该宏进行动态态组件的注册。相对于静态组件，动态组件的注册只会注册其类型，不会实例化空对象，后续业务方可在必要时机进行动态组件的注册。该宏定义：\n```objc\n#define CBUS_DYNAMIC_COMPONENT(name) \\\nCBUS_COMPONENT(#name) \\\n+ (BOOL)isDynamic { return YES; } \\\n```\n\n#### CBUS_ACTION\n`CBUS_ACTION(action)`\n\nCBus 为了能够正确识别匹配组件的目标方法，定义了该宏：\n```objc\n#define CBUS_ACTION(sel_name) \\\n- (void)__cbus_action__##sel_name:(CBus *)cbus CBUS_OBJC_DYNAMIC\n```\n可以看到，该宏为每个标记的组件方法，添加了 `__cbus_action__` 的前缀，并传入了一个当前调用的 CBus 对象，业务方可通过访问 `cbus` 实例来\n获取调用请求，或是设置返回调用结果。\n\n#### + isDynamic\n`+ (BOOL)isDynamic;`\n\n是否动态组件。\n\n#### + componentName\n`+ (NSString *)componentName;`\n\n当前组件名称。\n\n### CBusClient\nCBus 内核中持有一个默认的 CBusClient 对象，该对象是方法调用的实际管理者，其主要包含以下功能：\n* 初始化调用请求\n* 持有方法线程调度管理者\n* 设置全局的拦截器\n\n#### dispatcher\n`@property (nonatomic, strong, readonly) CBusDispatcher *dispatcher;`\n\n方法线程调度管理者，具体见 [CBusDispatcher](#CBusDispatcher) 。\n\n#### interceptors\n`@property (nonatomic, copy, readonly) NSArray\u003cid\u003cCBusInterceptor\u003e\u003e *interceptors;`\n\n自定义拦截器列表，全局生效。\n\n#### - newCall:\n`- (CBusRealCall *)newCall:(CBus *)cbus;`\n\n初始化一个调用请求。\n\n#### - addInterceptor:\n`- (void)addInterceptor:(id\u003cCBusInterceptor\u003e)interceptor;`\n\n添加一个拦截器。\n\n#### - addInterceptors:\n`- (void)addInterceptors:(NSArray\u003cid\u003cCBusInterceptor\u003e\u003e *)interceptors;`\n\n批量添加拦截器。\n\n### CBusRequest\n每次 CBus 的方法调用，都需要生成一个 CBusRequest 实例，该实例中包含了当前请求所有的信息。\n#### component\n`@property (nonatomic, copy, readonly) NSString *component;`\n\n目标组件名称。\n\n#### action\n`@property (nonatomic, copy, readonly) NSString *action;`\n\n目标组件方法名称。\n\n#### params\n`@property (nonatomic, strong, readonly) NSDictionary *params;`\n\n参数实体。\n\n#### timeout\n`@property (nonatomic, assign, readonly) NSTimeInterval timeout;`\n\n当前请求的超时时间。\n\n#### isDeliverOnMainThread\n`@property (nonatomic, assign, readonly) BOOL isDeliverOnMainThread;`\n\n是否在主线程结束回调。\n\n#### interceptors\n`@property (nonatomic, copy, readonly) NSArray\u003cid\u003cCBusInterceptor\u003e\u003e *interceptors;`\n\n当前请求的拦截器。\n\n#### 新建请求\n可通过以下两个方法，生成对应的请求实体：\n* `+ requestWithComponent:action:params:`\n* `+ requestWithComponent:action:params:timeout`;\n\n#### deliverOnMainThread\n`- (void)deliverOnMainThread;`\n\n结束回调切换回主线程。\n\n#### 添加拦截器\n可添加单个或多个拦截器：\n* `- (void)addInterceptor:(id\u003cCBusInterceptor\u003e)interceptor;`：添加一个请求拦截器\n* `- (void)addInterceptors:(NSArray\u003cid\u003cCBusInterceptor\u003e\u003e *)interceptors;`：批量添加请求拦截器\n\n#### 设置超时时间\n可直接通过 `aRequest.timeout = 4` 来手动设置超时时间。\n\n### CBusResponse\nCBusResponse 中包含了每个方法调用的响应结果。\n\n#### result\n`@property (nonatomic, strong, readonly) NSDictionary *result;`\n\n响应结果。\n\n#### code\n`@property (nonatomic, assign, readonly) CBusCode code;`\n\n响应码。\n\n#### success\n`@property (nonatomic, assign, readonly, getter=isSuccess) BOOL success;`\n\n是否响应成功。\n\n#### 生成响应结果\n根据不同场景，提供了以下方法用于快速生成不同响应结果：\n* `+ (instancetype)success:(NSDictionary *)result;`：快速返回一个成功结果，其 `code=1, isSuccess=YES`\n* `+ (instancetype)errorCode:(CBusCode)code;`：根据给定的 `code`，快速返回一个失败结果，其 `isSuccess=NO`\n* `+ (instancetype)error:(NSDictionary *)result;`：快速返回一个失败结果，其 `isSuccess=NO`\n* `+ (instancetype)error:(nullable NSDictionary *)result code:(CBusCode)code;`：快速返回一个自定义的失败结果，其 `isSuccess=NO`\n\n\n### CBusDispatcher\nCBus 所有的异步调用，都将加入到 CBusDispatcher 中维护的操作队列中，其默认的最大操作数是64。\n\n#### - enqueue:\n`- (void)enqueue:(CBusAsyncCall *)asyncCall;`\n\n开始执行一个异步调用。\n\n#### - onResult:completion:\n`- (void)onResult:(CBus *)cbus completion:(CBusAsyncCallCompletion)completion;`\n\n触发异步方法回调。\n\n#### - cancelAllCalls\n`- (void)cancelAllCalls;`\n\n取消所有的异步方法调用。\n\n### CBusInterceptor\nTODO\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fljunb%2Fcomponentbus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fljunb%2Fcomponentbus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fljunb%2Fcomponentbus/lists"}