我一直搞不清楚,方法method和selector(选择子)到底是啥关系,通过百度
在 Objective-C 中,selector,Method 和 implementation(IMP) 都是 Runtime 的组成部分。在实际开发中它们常常是可以相互转换来处理消息的发送的。选择子代表方法在 Runtime 期间的标识符。为 SEL 类型,虽然 SEL 是 objc_selector 结构体指针,但实际上它只是一个 C 字符串。在类加载的时候,编译器会生成与方法相对应的选择子,并注册到 Objective-C 的 Runtime 运行系统。
得出结论:
选择子其实是方法的名称,不同类中方法名相同参数不同的俩个方法,他们的选择子是相同的。
来看看Method的结构体
/// Method
struct objc_method {
SEL method_name;
char *method_types;
IMP method_imp;
};
- 方法名 method_name 类型为 SEL,前面提到过相同名字的方法即使在不同类中定义,它们的方法选择器也相同。
- 方法类型 method_types 是个 char 指针,其实存储着方法的参数类型和返回值类型,即是 Type Encoding 编码。(即类型编码)
- method_imp 指向方法的实现,本质上是一个函数的指针,就是前面讲到的 Implementation。
不知道大家有没有用过 (IMP)。
下面让我们来看看这个方法:
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);
这个方法主要接受四个参数
Class cls 要添加方法的类
SEL name 被添加方法的名字
IMP imp 添加的方法的实现
const char *types 描述方法参数类型的字符数组。
注意这个 IMP,如果你只是简单写了一个方法,像这样:
这个IMP是代表函数指针,即函数执行的入口。我们的方法的函数形式是
void method(id self, SEL _cmd);
默认俩个参数是方法调用者和方法名,看到了吗,这个SEL类型其实只是名字而已。
以上为 selector,Method 和 implementation(IMP) 的内容。
消息传递机制
Objective-C 语言 中,对象方法调用都是类似 [receiver selector]; 的形式,其本质就是让对象在运行时发送消息的过程。
c语言是静态绑定的语言,也就是在编译时就能觉得运行时你会调用什么函数,而OC是动态绑定。
让我们看看消息的流程
粘贴自不羁阁。
最后一条,临时添加对应的实现方法也在这个消息转发的过程中
所有 Objective-C 方法调用在编译时都会转化为对 C 函数 objc_msgSend 的调用。objc_msgSend(receiver,selector); 是 [receiver selector]; 对应的 C 函数。
消息转发机制
当我们在.h文件中写了一个方法,但是却没写实现,你会发现你可以调用这个方法,编译器在编译器不会报错,它相信在运行期可以找到方法实现,因为你没写,所以在运行的时候会崩。
当对象收到无法解读的消息后,首先将调用其所属类的一个方法
+ (BooL)resolveInstanceMethod:(SEL)sel
这里的sel就是我们刚刚调用的方法,应该叫选择子。这个方法表示这个类能否新增一个实例方法用来处理这个选择子,在继续向下执行转发机制之前,本类有机会新增一个处理此选择子的方法。
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSString *selectorString = NSStringFromSelector(sel);
Method method = class_getInstanceMethod([self class], @selector(rush));
if ([selectorString isEqualToString:@"rushB"]) {
class_addMethod(self, sel, method_getImplementation(class_getInstanceMethod([self class], @selector(rush))), method_getTypeEncoding(method));
return YES;
}
1.第一步首先将这个选择子转成字符串
2.第二步是为了获取他的type coding。前面写过这个class_addMethod.它有4个参数:
Class cls 要添加方法的类
SEL name 被添加方法的名字
IMP imp 添加的方法的实现
const char *types 描述方法参数类型的字符数组。
我们可以用查表的方式填写第四个参数,也可以用这个方法。
还有俩个方法都是将消息的接受者转移。
来源:CSDN
作者:wtl1804
链接:https://blog.csdn.net/wtl1804/article/details/104110011