版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wtdask/article/details/84144071
GitHub参考
PS:参考GitHub分享的objc-runtime-master
代码,及Runtime003
代码
查看Runtime源码
// No implementation found. Try method resolver once.
//如果这个方法没有被发现,就会尝试一次动态方法解析,一次过后`goto retry`,再次执行我们上一篇文章中介绍的查找方式
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;
}
// No implementation found, and method resolver didn't help.
// Use forwarding.
//如果执行完上面的操作都没有找到,进入消息转发阶段
imp = (IMP)_objc_msgForward_impcache;
cache_fill(cls, sel, imp, inst);
done:
runtimeLock.unlockRead();
return imp;
_class_resolveMethod
方法
void _class_resolveMethod(Class cls, SEL sel, id inst)
{
//如果不是元类,调用的实例方法 _class_resolveInstanceMethod
if (! cls->isMetaClass()) {
// try [cls resolveInstanceMethod:sel]
_class_resolveInstanceMethod(cls, sel, inst);
}
//如果是元类,调用 _class_resolveClassMethod
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);
}
}
}
代码示例:
main.m
#import <Foundation/Foundation.h>
#import "TZPerson.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
[[TZPerson new] walk];
}
return 0;
}
TZPerson.m
#import "TZPerson.h"
@implementation TZPerson
//- (void) walk {
// NSLog(@"%s", __func__);
//}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSLog(@"%s", __func__);
return [super resolveInstanceMethod:sel];
}
@end
TZPerson类的walk
方法没有被实现,方法调用没有被找到,会尝试一次动态方法解析,进入到+ (BOOL)resolveInstanceMethod:(SEL)sel;
方法中。
执行一次没有被找到,接下来进入消息转发___forwarding__
,再次执行resolveInstanceMethod
#import "TZPerson.h"
#import <objc/runtime.h>
@implementation TZPerson
//C语言方法
void walk() {
NSLog(@"%s", __func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSLog(@"%s", __func__);
// 元类
// 实例对象、类对象、元类对象
if (sel == @selector(walk)) {
return class_addMethod(self, sel, (IMP)walk, "v@:");
}
return [super resolveInstanceMethod:sel];
}
@end
执行结果:
2018-11-19 10:37:00.898842+0800 Runtime001[1284:51608] +[TZPerson resolveInstanceMethod:]
2018-11-19 10:37:00.899171+0800 Runtime001[1284:51608] walk
Program ended with exit code: 0
使用OC的方式添加
#import "TZPerson.h"
#import <objc/runtime.h>
@implementation TZPerson
-(void) run {
NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSLog(@"%s", __func__);
if (sel == @selector(walk)) {
Method runMethod = class_getInstanceMethod(self, @selector(run));
IMP runIMP = method_getImplementation(runMethod);
const char* types = method_getTypeEncoding(runMethod);
NSLog(@"%s", types);
return class_addMethod(self, sel, runIMP, types);
}
return [super resolveInstanceMethod:sel];
}
@end
执行结果
2018-11-19 10:48:17.163472+0800 Runtime001[1339:56488] +[TZPerson resolveInstanceMethod:]
2018-11-19 10:48:17.163783+0800 Runtime001[1339:56488] v16@0:8 //16表示参数一共所占的字节数;@表示从第几个字节开始;:表示第8个字节
2018-11-19 10:48:17.163803+0800 Runtime001[1339:56488] -[TZPerson run]
Program ended with exit code: 0
类方法调用
ps:参考gitHub代码Runtime004
#import <Foundation/Foundation.h>
#import "TZPerson.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
[TZPerson walk];
}
return 0;
}
#import "TZPerson.h"
#import <objc/runtime.h>
@implementation TZPerson
+ (void) run {
NSLog(@"%s", __func__);
}
+ (BOOL)resolveClassMethod:(SEL)sel {
if (sel == @selector(walk)) {
Method runMethod = class_getClassMethod(self, @selector(run));
IMP runIMP = method_getImplementation(runMethod);
const char* types = method_getTypeEncoding(runMethod);
NSLog(@"%s", types);
return class_addMethod(object_getClass(self), sel, runIMP, types);
}
return [super resolveClassMethod:sel];
}
@end