SEL
objc_msgSend
函数第二个参数类型为SEL
,它是selector在Objc
中的表示类型(Swift中是Selector类)。selector
是方法选择器,可以理解为区分方法的ID
,而这个 ID
的数据结构是SEL:
typedef struct objc_selector *SEL;
其实它就是个映射到方法的C字符串
,你可以用 Objc 编译器命令 @selector()
或者 Runtime 系统的 sel_registerName
函数来获得一个 SEL
类型的方法选择器。
不同类中相同名字的方法所对应的方法选择器是相同的,即使方法名字相同而变量类型不同也会导致它们具有相同的方法选择器,于是 Objc
中方法命名有时会带上参数类型
IMP
IMP
在objc.h
中的定义是:
typedef void (*IMP)(void /* id, SEL, ... */ );
它就是一个函数指针
,这是由编译器生成的。当你发起一个 ObjC 消息之后,最终它会执行的那段代码,就是由这个函数指针指定的。而 IMP
这个函数指针就指向了这个方法的实现。既然得到了执行某个实例某个方法的入口,我们就可以绕开消息传递阶段,直接执行方法,这在后面会提到。
你会发现 IMP
指向的方法与 objc_msgSend
函数类型相同,参数都包含 id
和 SEL
类型。每个方法名都对应一个 SEL
类型的方法选择器,而每个实例对象中的 SEL
对应的方法实现肯定是唯一的,通过一组 id
和 SEL
参数就能确定唯一的方法实现地址;反之亦然。
-
SEL 是方法编号,即方法名称,在dyld加载镜像时,通过read_image方法加载到内存的表中了。
-
IMP 是函数实现指针,保存了方法的地址,找IMP就是找函数的过程
两者的关系:sel相当于书本的目录标题,imp就是书本的页码。查找具体的函数就是想看这本书里面具体篇章的内容:
1). 我们首先知道想看什么,也就是title -sel
2). 然后根据目录对应的页码 -imp
3). 打开具体的内容 -方法的具体实现
网友评论