runtime之SEL与IMP

SEL

首先,SEL是一个选择器,我们来看看SEL在runtime中的定义:

/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;

可见SEL是一个指向objc_selector结构体的指针。
那么selector有什么用呢,当我们执行方法调用的时候,OC会根据selector来执行对应的方法。
但是,两个类之间,不管他们有没有关系,只要他们类中的方法名一样,那么他们的SEL是同一个值。!!!
这里我用一个例子来演示一下:
首先定义一个Person类,并定义一个run方法:

@implementation Person

-(void) run{
    NSLog(@"I like running");
}

@end

然后在主函数中,我通过两种不同的方法获取方法run的selector,并打印这两个selector的地址。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    	//方法一获取run的selector
        SEL selector = @selector(run);
        NSLog(@"selector address : %p",selector);
       
       	//方法2获取run的selector
        const char * methodName = [@"run" UTF8String];
        SEL selectorFromName = sel_registerName(methodName);
        NSLog(@"selectorFromName address : %p",selectorFromName);
        //执行后,可以看到,通过两种不同方法获得的selector,他们的地址是一样的
    }
    return 0;
}

执行结果:

2021-03-18 14:27:10.369837+0800 Project06[83997:4736657] selector address : 0x7fff7c300f34
2021-03-18 14:27:10.370205+0800 Project06[83997:4736657] selectorFromName address : 0x7fff7c300f34
Program ended with exit code: 0

可以看到,两个selector的地址是一模一样的,所以他们具有一样的selector!!
因此,在OC中,同一个中不允许出现同名的方法,即使他们的方法参数不一样也不行,因为这会导致他们的SEL相同。(即OC中不存在函数的重载!)

那么问题来了,两个方法的selector的一样,那么我们在执行类的对应方法的时候,是如何定位到指定类的指定方法的呢?
这时候,IMP的作用就体现了。

IMP

IMP:implementation (实现体)
其在runtime源码中的定义是:

typedef void (*IMP)(void /* id, SEL, ... */ ); 

可见IMP是一个函数指针。
如图,当我们在两个类都调用run方法
在这里插入图片描述
而每一个方法在runtime都被定义为一个结构体:

struct objc_method {
    SEL _Nonnull method_name                                 OBJC2_UNAVAILABLE;
    char * _Nullable method_types                            OBJC2_UNAVAILABLE;
    IMP _Nonnull method_imp                                  OBJC2_UNAVAILABLE;
}    

,结构体有三个元素,虽然他们的SEL是一样的,但是根据IMP不一样,我们就可以定位到指定类的指定方法了。而不会出现不同类中的同名方法定位模糊的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值