objc_msgSend()实现
2.动态解析阶段:
1. 判断之前是否动态解析过:
- 没解析,进入判断,并在解析完成后,标志位置位YES:
triedResolver = YES
;
if (resolver && !triedResolver) {
runtimeLock.unlockRead();
_class_resolveMethod(cls, sel, inst);
runtimeLock.read();
// Don't cache the result; we don't hold the lock so it may have
// changed already. Re-do the search from scratch instead.
triedResolver = YES;
goto retry;
}
2. 进入动态解析:_class_resolveMethod(cls, sel, inst);
- 根据你这个类是
类对象
还是元类对象
调用不同的方法: [cls resolveInstanceMethod:sel]
[nonMetaClass resolveClassMethod:sel]
void _class_resolveMethod(Class cls, SEL sel, id inst)
{
if (! cls->isMetaClass()) {
// try [cls resolveInstanceMethod:sel]
_class_resolveInstanceMethod(cls, sel, inst);
}
else {
// try [nonMetaClass resolveClassMethod:sel]
// and [cls resolveInstanceMethod:sel]
_class_resolveClassMethod(cls, sel, inst);
if (!lookUpImpOrNil(cls, sel, inst,
NO/*initialize*/, YES/*cache*/, NO/*resolver*/))
{
_class_resolveInstanceMethod(cls, sel, inst);
}
}
}
如何实现:
举例: Person类中只有一个实例方法 - (void)test;
的声明;
方法一:
- 直接使用
method
- (void)other {
NSLog(@"%s", __func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(test)) {
// 获取其他方法
Method method = class_getInstanceMethod(self, @selector(other));
// 动态添加test方法的实现
class_addMethod(self, sel,
method_getImplementation(method),
method_getTypeEncoding(method));
// 返回YES代表有动态添加方法
return YES;
}
return [super resolveInstanceMethod:sel];
}
方法二:
- 自定义
method_t
:
struct method_t {
SEL sel;
char *types;
IMP imp;
};
- (void)other {
NSLog(@"%s", __func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(test)) {
// 获取其他方法
struct method_t *method = (struct method_t *)class_getInstanceMethod(self, @selector(other));
// 动态添加test方法的实现
class_addMethod(self, sel, method->imp, method->types);
// 返回YES代表有动态添加方法
return YES;
}
return [super resolveInstanceMethod:sel];
}
方法三:
- 调用C语言函数:
void c_other(id self, SEL _cmd) {
NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
}
+ (BOOL) resolveInstanceMethod:(SEL)sel {
if (sel == @selector(test)) {
// 第一个参数是object_getClass(self)
class_addMethod(self, sel, (IMP)c_other, "v16@0:8");
return YES;
}
return [super resolveInstanceMethod:sel];
}
如果是调用类方法:+ (void)test
+ (BOOL)resolveClassMethod:(SEL)sel {
if (sel == @selector(test)) {
//object_getClass(self) 获取当前类
Method methodClass = class_getClassMethod(object_getClass(self), @selector(other));
class_addMethod(object_getClass(self), sel, method_getImplementation(methodClass), method_getTypeEncoding(methodClass));
return YES;
}
return [super resolveClassMethod:sel];
}
动态解析流程图:
- 先判断该方法是否进行过动态解析;
- 如果没有,调用
+ (BOOL) resolveInstanceMethod:(SEL)sel
或+ (BOOL)resolveClassMethod:(SEL)sel
来进行动态方法解析; - 动态方法解析如果有实现:会有一个
class_addMethod
函数,将方法添加到类对象的class_rw_t
的methods
; - 不管动态方法解析阶段有没有方法实现,是否进行过动态解析标志位都会置为YES:
triedResolver = YES
; - 并再返回第一步消息发送阶段,进行方法查找:
goto retry
:- 如果动态解析有方法实现,方法查找阶段就会在
class_rw_t
的methods
中找到方法; - 如果动态解析方法没有实现,方法仍旧找不到;
- 如果动态解析有方法实现,方法查找阶段就会在
- 进入消息转发阶段。