实例对象方法动态解析
static void resolveInstanceMethod(id inst, SEL sel, Class cls)
{
runtimeLock.assertUnlocked();
ASSERT(cls->isRealized());
SEL resolve_sel = @selector(resolveInstanceMethod:);
if (!lookUpImpOrNilTryCache(cls, resolve_sel, cls->ISA(/*authenticated*/true))) {
// Resolver not implemented.
return;
}
BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
bool resolved = msg(cls, resolve_sel, sel);
// Cache the result (good or bad) so the resolver doesn't fire next time.
// +resolveInstanceMethod adds to self a.k.a. cls
IMP imp = lookUpImpOrNilTryCache(inst, sel, cls);
if (resolved && PrintResolving) {
if (imp) {
_objc_inform("RESOLVE: method %c[%s %s] "
"dynamically resolved to %p",
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel), imp);
}
else {
// Method resolver didn't add anything?
_objc_inform("RESOLVE: +[%s resolveInstanceMethod:%s] returned YES"
", but no new implementation of %c[%s %s] was found",
cls->nameForLogging(), sel_getName(sel),
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel));
}
}
}
类方法动态解析
static void resolveClassMethod(id inst, SEL sel, Class cls)
{
runtimeLock.assertUnlocked();
ASSERT(cls->isRealized());
ASSERT(cls->isMetaClass());
if (!lookUpImpOrNilTryCache(inst, @selector(resolveClassMethod:), cls)) {
// Resolver not implemented.
return;
}
Class nonmeta;
{
mutex_locker_t lock(runtimeLock);
nonmeta = getMaybeUnrealizedNonMetaClass(cls, inst);
// +initialize path should have realized nonmeta already
if (!nonmeta->isRealized()) {
_objc_fatal("nonmeta class %s (%p) unexpectedly not realized",
nonmeta->nameForLogging(), nonmeta);
}
}
BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
bool resolved = msg(nonmeta, @selector(resolveClassMethod:), sel);
// Cache the result (good or bad) so the resolver doesn't fire next time.
// +resolveClassMethod adds to self->ISA() a.k.a. cls
IMP imp = lookUpImpOrNilTryCache(inst, sel, cls);
if (resolved && PrintResolving) {
if (imp) {
_objc_inform("RESOLVE: method %c[%s %s] "
"dynamically resolved to %p",
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel), imp);
}
else {
// Method resolver didn't add anything?
_objc_inform("RESOLVE: +[%s resolveClassMethod:%s] returned YES"
", but no new implementation of %c[%s %s] was found",
cls->nameForLogging(), sel_getName(sel),
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel));
}
}
}
实例介绍
@interface MJPerson : NSObject
//- (void)test;
+ (void)test;
@end
#import "MJPerson.h"
#import <objc/runtime.h>
@implementation MJPerson
//void c_other(id self, SEL _cmd)
//{
// NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
//}
//
//+ (BOOL)resolveClassMethod:(SEL)sel
//{
// if (sel == @selector(test)) {
// // 第一个参数是object_getClass(self)
// class_addMethod(object_getClass(self), sel, (IMP)c_other, "v16@0:8");
// return YES;
// }
// return [super resolveClassMethod:sel];
//}
//+ (BOOL)resolveInstanceMethod:(SEL)sel
//{
// if (sel == @selector(test)) {
// // 动态添加test方法的实现
// class_addMethod(self, sel, (IMP)c_other, "v16@0:8");
//
// // 返回YES代表有动态添加方法
// return YES;
// }
// return [super resolveInstanceMethod:sel];
//}
//- (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];
//}
// typedef struct objc_method *Method;
// struct objc_method == struct method_t
// struct method_t *otherMethod = (struct method_t *)class_getInstanceMethod(self, @selector(other));
struct method_t {
SEL sel;
char *types;
IMP imp;
};
//+ (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];
//}
@end
//运行
// MJPerson *person = [[MJPerson alloc] init];
// [person test];
[MJPerson test];
- 虽然这个test方法没有实现但是最后还是会调用到test方法
- 这个其实没有多大的使用场景做个了解就好了
流程图
- 开发者可以实现以下方法,来动态添加方法实现
- +resolveInstanceMethod:
- +resolveClassMethod:
- 动态解析过后,会重新走“消息发送”的流程
- “从receiverClass的cache中查找方法”这一步开始执行