SEL:类成员方法的指针,但是不同于C语言中的函数指针,函数指针直接保存了方法的地址,
但是SEL只是方法编号。
IMP:一个函数指针,保存了方法的地址。每一个继承于NSObject的类都能自动获取runtime
的支持,在这样的一个类中,有一个isa指针,指向该类定义的数据结构体,这个结构体是由
编译器编译时为类创建的(需要该类继承于NSObject,在编译的时候,编译器自动为程序中
类在内存中开辟空间,存储这个结构体)。在这个结构体中就有一个Dispatch table的表,是
一张SEL和IMP对应的表。
@selector()用于获取方法的编号(在objc中存在一个name-selector的映射表),方法编号
SEL最后还要通过Dispatch table表寻找到对应的IMP(runtime为了提高查找效率引入了
Class Cache机制,也就是每次调用的方法先放到Cache中,下次再查询时先去Cache中
查询没有的话再去Dispatch table中查询),IMP就是一个函数指针,找到方法的
地址,然后执行这个方法。(IMP指针在方法执行体(objc_method)中)
编号获取后执行方法:[self performSelector:methodId withObject:nil];
通过编号获取方法名:
NSString *methodName = NSStringFromSelector(methodId);
IMP怎么获取和使用
IMP methodPoint = [self methodForSelector:methodId];
methodPoint();
从SEL寻找IMP再执行方法比直接用IMP执行方法的好处:
有这个SEL的中间环节,我们可以对方法名字和编号进行映射操作,可以让SEL指向不同的函数
指针,完成一个方法名在不同的时候执行不同的函数体。也可以将SEL作为参数传递给不同的类
执行。
参考文章:https://www.jianshu.com/p/4a09d5ebdc2c