概述
IMBeeHive是用于iOS的App模块化编程的框架实现方案,本项目主要借鉴了阿里巴巴BeeHive,在此基础上通过逆向了一些大厂的APP使得功能更加强大完善。同时现在也在寻找一起开发这个框架的开发者,如果您对此感兴趣,请联系我的微信:alvinkk01.
背景
随着公司业务的不断发展,项目的功能越来越复杂,各个业务代码耦合也越来越多,解耦合和业务组件化(或者叫模块化)也迫在眉睫。 在网上组件化的文章很多,主要方案有三种:1.protocol-class 2.target-action 3.route,后来通过逆向一些大厂的app,发现这些组件化(或者叫模块化)的技术在大厂使用率挺高的,基本上也是基于这三种方案,但各家都是不同的实现方式,于是乎就萌生了开发一个组件化框架的想法,开发者可以根据自己的喜好选择自己喜欢的方案实现解耦和业务组件化,而不需要重复造轮子。
完整DEMO
https://github.com/DebugAlvin/IMAudioLive
项目特色
组件管理生命周期
组件间通信
使用protocol-class方案service无需注册
支持route(计划更新)
Installation
pod "IMBeeHive"
初始化
一.首先我们需要在主工程添加一个配置文件,这里我添加的是IMBeeHive.bundle/IMBeeHive.plist,通过配置plist我们可以在启动时注册所有的Moudle,实际开发的项目Moudle并不会很多,我目前开发的项目大概也就8个Moudle,IMLuanchMoudle、IMHomeMoudle、IMDynamicMoudle、IMChatMoudle、IMMineMoudle...,所以在推荐在plist里面统一注册Moudle
二.在主主工程加入__attribute__((constructor)),通常app启动流程为:
1.所有Framework的+load方法
2.所有Framework的c++构造方法
3.主程序的+load方法
4.主程序的c++构造方法
我们在主程序Appdelegate之前做初始化,IMBeeHive才可以通过HOOK + NSInvocation方式让已经注册的Moudle管理Appdelegate的生命周期
__attribute__((constructor)) void loadBeeHiveMoudle () {
[IMBeeHive shareInstance].context.configName = @"IMBeeHive.bundle/IMBeeHive";//可选,默认为IMBeeHive.bundle/IMBeeHive
[[IMBeeHive shareInstance] registerAll]; //从配置里面注册所有moudle或者service
[[IMBeeHive shareInstance] setupAll]; //设置ioc容器里面所有的对象
}
创建Moudle
一.使用cocopods创建Moudle
首先cd到主程序目录,然后执行命令pod lib create xxxxx
pod lib create IMLuanchMoudle
将会询问以下内容:
1.What Language do you want to use?? [Swift / objC]
2.Would you like to include a demo application with your Library? [Yes / No]
3.Would you like to do view based testing? [Yes / No]
4.What is your class prefix?
创建成功后会打开Xcode
Example可以作为我们的壳工程,平时对模块的开发和调试可以在这里进行。另外我们需要配置IMLuanchMoudle.podspec,具体方法请参考DEMO
新建一个IMLaunchModuleProtocol.h,值得注意的是我们必须遵循IMModuleProtocol协议
#import
/**
The services provided by Launch module to other modules
*/
@protocol IMLaunchModuleProtocol
-(void)doSomeTings;
@end
新建一个IMLuanchMoudle.h和IMLuanchMoudle.m
//IMLuanchMoudle.h
#import
#import "IMLaunchModuleProtocol.h"
static UIWindow *mWindow = nil;
NS_ASSUME_NONNULL_BEGIN
@interface IMLuanchMoudle : NSObject
@end
NS_ASSUME_NONNULL_END
//IMLuanchMoudle.m
#import "IMLuanchMoudle.h"
#import "IMLuanchViewController.h"
@implementation IMLuanchMoudle
//每个Moudle必须实现shareInstance方法,编译器会提醒
+ (instancetype)shareInstance {
static dispatch_once_t p;
static id Instance = nil;
dispatch_once(&p, ^{
Instance = [[self alloc] init];
});
return Instance;
}
//如果我们当前的模块是主模块,我们可以实现didFinishLaunchingWithOptions设置rootViewController
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"[IMLuanchMoudle] --- [执行]");
mWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
mWindow.backgroundColor = [UIColor whiteColor];
[mWindow makeKeyAndVisible];
[UIApplication sharedApplication].delegate.window = mWindow;
mWindow.rootViewController = [[IMLuanchViewController alloc] init];
return YES;
}
- (void)doSomeTings {
NSLog(@"通过IMLaunchModuleProtocol协议调用IMLuanchMoudle的doSomeTings方法");
}
模块间的互相调用
首先我们需要在Protocol暴露方法
#import
#import
@protocol IMMineModuleProtocol
- (UIViewController *)mainViewController;
-(void)doSomeTingsA;
-(void)doSomeTingsB;
@end
然后在Protocol的实现类实现这些方法
#import "IMMineModule.h"
#import "IMMIneViewController.h"
@implementation IMMineModule
+ (instancetype)shareInstance {
static dispatch_once_t p;
static id Instance = nil;
dispatch_once(&p, ^{
Instance = [[self alloc] init];
});
return Instance;
}
-(UIViewController *)mainViewController {
IMMIneViewController *controller = [[IMMIneViewController alloc] init];
return controller;
}
- (void)doSomeTingsA {
NSLog(@"通过IMLaunchModuleProtocol协议调用IMLuanchMoudle的doSomeTingsA方法");
}
- (void)doSomeTingsB {
NSLog(@"通过IMLaunchModuleProtocol协议调用IMLuanchMoudle的doSomeTingsB方法");
}
@end
最后我们可以在任意模块通过Protocol调用实现类的方法
id
pModule = IMGetBean(IMMineModuleProtocol);
[pModule doSomeTingsA];
[pModule doSomeTingsB];
UIViewController *controller = [pModule mainViewController];
[self.navigationController pushViewController:controller animated:YES];