No title
先说一个大家都熟悉的 SEL
ID 就是```SEL```类型的。我们需要注意的是,只要方法的名字和参数序列完全相同,那么它们的 ID编号就是相同的。(这里我先提出个问题,既然```SEL```是方法的唯一标识,那不同的类调用名字相同的方法怎么办呢?稍后解答。。。)
1 >#####常见的几种方法来获取/创建选择器:SEL aSel = @selector(didReceiveMemoryWarning);
SEL a_sel = NSSelectorFromString(@”didReceiveMemoryWarning”);
SEL a_Sel = sel_registerName(“didReceiveMemoryWarning”);
1 | 打印结果: |
[5192:325263] 0x1214054bc___0x1214054bc___0x1214054bc
1 | SEL的操作函数: |
// 比较两个选择器
BOOL sel_isEqual ( SEL lhs, SEL rhs );
//判断方法名是否映射到某个函数实现上
BOOL sel_isMapped(SEL sel);
1 |
|
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (IMP)(void / id, SEL, … */ );
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, …);
#endif
1 | 其参数包含id,SEL,后面试实际的参数列表。 |
//通过Method获取IMP
IMP method_getImplementation(Method m);
// 返回方法的具体实现
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );
1 | 获取到```IMP```之后可直接调用方法: |
SEL aSel = @selector(didReceiveMemoryWarning);
Method method = class_getInstanceMethod([self class], aSel);
IMP imp = method_getImplementation(method);
((void (*) (id, SEL)) (void *)imp)(self, aSel);
1 |
|
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;//方法实现指针
} OBJC2_UNAVAILABLE;
1 |
|
// 获取实例方法
Method class_getInstanceMethod ( Class cls, SEL name );
// 获取类方法
Method class_getClassMethod ( Class cls, SEL name );
// 获取所有方法的数组
Method * class_copyMethodList ( Class cls, unsigned int *outCount );
```
#总结:
消息机制:任何方法的调用本质就是发送一个消息。编译器会将消息表达式
[receiver message]
转化为一个消息函数objc_msgSend(receiver, selector)
。objc_msgSend
做了如下事情:通过对象的
isa
指针获取类的结构体。
在结构体的方法表里查找方法的selector
。
如果没有找到selector
,则通过objc_msgSend
结构体中指向父类的指针找到父类,并在父类的方法表里查找方法的selector
。
依次会一直找到NSObject
。
一旦找到selector
,就会获取到方法实现IMP
。
传入相应的参数来执行方法的具体实现。
如果最终没有定位到selector,就会走消息转发流程
![image-20230109102526365](/Users/david/Library/Application Support/typora-user-images/image-20230109102526365.png)