WX_EXPORT_METHOD
是暴露module方法的宏定义,展开后为:
#define WX_EXPORT_METHOD(method)
+ (NSString *)wx_export_method_ __LINE__ { \
return NSStringFromSelector(method); \
}
注册方法在WXInvocationConfig
里的registerMethods
里,代码如下:
- (void)registerMethods
{
Class currentClass = NSClassFromString(_clazz);
if (!currentClass) {
WXLogWarning(@"The module class [%@] doesn't exit!", _clazz);
return;
}
while (currentClass != [NSObject class]) {
unsigned int methodCount = 0;
Method *methodList = class_copyMethodList(object_getClass(currentClass), &methodCount);
for (unsigned int i = 0; i < methodCount; i++) {
NSString *selStr = [NSString stringWithCString:sel_getName(method_getName(methodList[i])) encoding:NSUTF8StringEncoding];
BOOL isSyncMethod = NO;
if ([selStr hasPrefix:@"wx_export_method_sync_"]) {
isSyncMethod = YES;
} else if ([selStr hasPrefix:@"wx_export_method_"]) {
isSyncMethod = NO;
} else {
continue;
}
NSString *name = nil, *method = nil;
SEL selector = NSSelectorFromString(selStr);
if ([currentClass respondsToSelector:selector]) {
method = ((NSString* (*)(id, SEL))[currentClass methodForSelector:selector])(currentClass, selector);
}
if (method.length <= 0) {
WXLogWarning(@"The module class [%@] doesn't has any method!", _clazz);
continue;
}
// 以冒号为分割,获取前半部分为方法名
NSRange range = [method rangeOfString:@":"];
if (range.location != NSNotFound) {
name = [method substringToIndex:range.location];
} else {
name = method;
}
NSMutableDictionary *methods = isSyncMethod ? _syncMethods : _asyncMethods;
[methods setObject:method forKey:name];
}
free(methodList);
currentClass = class_getSuperclass(currentClass);
}
}
可以看到,他用冒号来分割了字符串,只取了前半部分为方法字典的key
,因此这样的两个方法:WX_EXPORT_METHOD(@selector(test:param:))
和 @selector(test:)
在同一个module里会互相覆盖,只保留了前一个。这点需要在写方法的时候加以注意。