SEL:类成员的方法指针,不同于C中的函数指针,SEL只是一个编号。
IMP: 函数指针,指向我们定义的函数
SEL和IMP的关系
任何继承NSObject的类都会的得到runtime的支持,在类中有一个isa指针,指向该类定义的成员组成的结构体,这个结构体是编译时编译器为(NSObject)类创建的,在这个结构体中包含一个指向父类的指针和一个Dispatch table(分发表),这个Dispatch table 指明了SEL 和 IMP 的对应关系。
例:
一个方法
-(void)addMehtod:(NSString *)str
{
}
在执行时,编译器会找这个方法在类中的编号,这里假设是10,执行时实际是执行
objc_msgSend(addMehtod, 10, str);//方法名,编号,参数
OC中SEL 和 IMP的互相转换。
方法1(C函数)
void addMethod(id self,SEL _cmd,NSString *str){}
直接就用IMP指针接收
IMP imp = (IMP)addMethod;
方法2
-(void)addNewMethod:(NSString *)str{}
取得SEL的方法
SEL sel = @selector(addNewMethod:);
取得方法名(编号)
NSString *methodName1 = NSStringFromSelector(@selector(addNewMethod:));
取得IMP指针
IMP imp = [self methodForSelector:@selector(addNewMethod:)]
或者
IMP imp = [NSObject instanceMethodForSelector:@selector(addNewMethod:)]
为什么不直接获得函数指针,而要从SEL这个编号走一圈再回到函数指针呢?
有了SEL这个中间过程,我们可以对一个编号和什么方法映射做些操作,也就是说我们可以一个SEL指向不同的函数指针,这样就可以完成一个方法名在不同时候执行不同的函数体。另外可以将SEL作为参数传递给不同的类执行。也就是说我们某些业务我们只知道方法名但需要根据不同的情况让不同类执行的时候,SEL可以帮助我们