在objc/runtime.h文件中:
typedef struct objc_method *Method;
struct objc_method {
//方法选择器 方法名
SEL _Nonnull method_name OBJC2_UNAVAILABLE;
//参数和返回类型
char * _Nullable method_types OBJC2_UNAVAILABLE;
//方法实现的指针
IMP _Nonnull method_imp OBJC2_UNAVAILABLE;
}
Method的结构体中包含 SEL, method_types, IMP
SEL _Nonnull method_name
SEL 和_cmd, super一样都是运行时的标识符,SEL可以认为是函数名(method_name);
使用:
//通过@selector创建
SEL sel = @selector(function:);
//runtime sel_registerName创建
SEL sel = sel_registerName("function:");
在objc/source/objc-sel.mm中有:
const char *sel_getName(SEL sel)
{
if (!sel) return "<null selector>";
return (const char *)(const void*)sel;
}
sel通过类型转换成const char * ,SEL相当于const char *类型
通过lldb查看 method_name
SEL sel1 = @selector(function1:);
SEL sel2 = sel_registerName("function2:");
IMP
/// A pointer to the function of a method implementation.
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ );
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...);
#endif
OBJC_OLD_DISPATCH_PROTOTYPES 表示是否需要包IMP转为函数指针可以
在IMP中 必有两个参数 第一个是 id 对应的是self 第二个是SEL 这也就是 在OC的方法中 我们可以使用self和_cmd
IMP 指向方法实现的指针
//runtime 中的方法
//通过Class 和 SEL
IMP imp1 = class_getMethodImplementation(self.class, @selector(helloWorld:));
//通过Method
Method method = class_getInstanceMethod(self.class, @selector(helloWorld:));
IMP imp2 = method_getImplementation(method);
//NSObject 中的方法 通过SEL
IMP imp3 = [self methodForSelector:@selector(helloWorld:)];
IMP imp4 = [self.class instanceMethodForSelector:@selector(helloWorld:)];//类方法
//IMP调用
//定义函数指针
void (*helloWorld)(id, SEL, NSString *);
//转换类型
helloWorld = (void(*)(id, SEL, NSString *))imp1;
//调用
helloWorld(self, @selector(helloWorld:),@"helloWorkd");
//helloWorld 方法
-(void)helloWorld:(NSString *)string{
NSLog(@"%@",string);
}
method_types 参数和返回参数类型
//上面的 helloWorld 方法
Method method = class_getInstanceMethod(self.class, @selector(helloWorld:));
const char *typeEncoding = method_getTypeEncoding(method);
NSString *typeEncodingString = [NSString stringWithUTF8String:typeEncoding];
NSLog(@"%@",typeEncodingString);
把v24@0:8@16 中的数字去掉 v@? (数字具体表示什么不清楚,有明白的大佬请留言说明下多谢) 这些分别对应
v 返回值是void
第一个@上面中提及的IMP中第一个参数 self
: 代表上面中提及的IMP中第一个参数 SEL
最后一个@代码参数string
具体什么类型对应什么字符请参考官方文档
当我们调用方法是, 方法查找顺序是 objc_cache -> objc_method_list -> super objc_cache -> super objc_method_list…
objc_cache 中存放的是调用过的方法,来提高系统运行速度
猜测:通过比较SEL来找到method然后在找到IMP runtime中 sel_isEqual(SEL _Nonnull lhs, SEL _Nonnull rhs) SEL比较方法