Objective-C Method SEL IMP

在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比较方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值