好玩的点
宏的使用 Annotation方式注册
BeeHiveMod(ShopModule)
#define BeeHiveMod(name) \
char * k##name##_mod BeeHiveDATA(BeehiveMods) = ""#name"";
#define BeeHiveDATA(sectname) __attribute((used, section("__DATA,"#sectname" ")))
// 结果
char * kShopModule_mod __attribute((used, section("__DATA,""BeehiveMods"" "))) = """ShopModule""";
__attribute
__attribute第一个参数used很有用。 这个关键字是用来修饰函数的。
被used修饰以后,意味着即使函数没有被引用,在Release下也不会被优化。
如果不加这个修饰,那么Release环境链接器下会去掉没有被引用的段。
程序源程序代码被编译之后会主要分成两个段:程序指令和程序数据。代码段属于程序指令,数据段和.bss段属于数据段
可以出一个连线题了哈哈.png
既然 被放入了数据段的 __DATA,""BeehiveMods
BeehiveMods
段中
那Module的取出方法?
static NSArray<NSString *>* BHReadConfiguration(char *section)
{
NSMutableArray *configs = [NSMutableArray array];
Dl_info info;
dladdr(BHReadConfiguration, &info);
#ifndef __LP64__
// const struct mach_header *mhp = _dyld_get_image_header(0); // both works as below line
const struct mach_header *mhp = (struct mach_header*)info.dli_fbase;
unsigned long size = 0;
// 找到之前存储的数据段(Module找BeehiveMods段 和 Service找BeehiveServices段)的一片内存
uint32_t *memory = (uint32_t*)getsectiondata(mhp, "__DATA", section, & size);
#else /* defined(__LP64__) */
const struct mach_header_64 *mhp = (struct mach_header_64*)info.dli_fbase;
unsigned long size = 0;
uint64_t *memory = (uint64_t*)getsectiondata(mhp, "__DATA", section, & size);
#endif /* defined(__LP64__) */
// 把特殊段里面的数据都转换成字符串存入数组中
for(int idx = 0; idx < size/sizeof(void*); ++idx){
char *string = (char*)memory[idx];
NSString *str = [NSString stringWithUTF8String:string];
if(!str)continue;
BHLog(@"config = %@", str);
if(str) [configs addObject:str];
}
return configs;
}
疑惑的地方
char *string = (char*)memory[idx];
// 这里的 idx 不用每次偏移 `sizeof(void*)` 的距离吗
还是没看懂这个结构啊
注册方式 分为三种
- 宏
- 本地plist
- load 方式
注册对象: 必须遵守协议, 只有被 manager 管理,才能接收事件的分发
事件的分发
一般做法是把BHAppDelegate接管原来的AppDelegate。
注意这里所有的Module必须是遵循BHModuleProtocol的,否则无法接收到这些事件的消息。
业务自定义事件
- (void)triggerEvent:(BHModuleEventType)eventType
{
switch (eventType) {
default:
[BHContext shareInstance].customEvent = eventType;
[self handleModuleEvent:kAppCustomSelector];
break;
}
}
BeeHive模块调用
在BeeHive中是通过BHServiceManager来管理各个Protocol的。BHServiceManager中只会管理已经被注册过的Protocol。
在存储allServices数组的时候,是要加锁的。这里的lock是NSRecursiveLock。防止出现递归引起的线程安全问题。
?? 这里存在异步多线程调用吗, 为什么会加锁. 还是得看源码
网友评论