基础数据类型
SEL
又叫选择器,是表示一个方法的selector的指针,其定义如下:
typedef struct objc_selector *SEL;
objc_selector结构体的详细定义没有在<objc/runtime.h>头文件中找到。方法的selector用于表示运行时方法的名字.Objective-C在编译时会依据每一个方法的名字,参数序列,生成一个唯一的整型标识(Int类型的地址),这个标识就是SEL
两个类之间,只要方法名相同,那么方法的SEL就是一样的.每个方法对应着一个SEL,所以在Objective-C同一个类和子类中不能存在2个同名的方法,即使参数类型不同也不行。相同的方法只能对应一个SEL。
当然不同的类可以拥有相同的selector,因为不同的类的实例对象执行相同的selector时,会在各自的方法列表中去寻找对应的IMP。
SEL实际上就是根据方法名hash化了的一个字符串,SEL只是一个指向方法的指针(准确的说,只是一个根据方法名hash化了的KEY值,能唯一代表一个方法)。
IMP
实际上是一个函数指针,指向方法实现的首地址
id(*IMP)(id SEL,...)
第一个参数指向self的指针(如果是实例方法,则是类实例的内存地址,如果是类方法,则是指向元类的指针),第二个参数是方法选择器(selector),接下来是方法的实际参数列表。
Method
Method用于表示类定义中的方法
typedef struct objc_method *Method;
struct objc_method{
SEL method_name OBJC2_UNAVAILABLE;//方法名
char *method_type OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;//方法实现
}
我们可以看到该结构体中包含一个SEL和IMP,实际上相当于在SEL和IMP之间作了一个映射。有了SEL,我们便可以找到对应的IMP,从而调用方法的实现代码。具体操作流程我们将在下面讨论。
方法
// 调用指定方法的实现
id method_invoke ( id receiver, Method m, ... );
// 调用返回一个数据结构的方法的实现
void method_invoke_stret ( id receiver, Method m, ... );
// 获取方法名
SEL method_getName ( Method m );
// 返回方法的实现
IMP method_getImplementation ( Method m );
// 获取描述方法参数和返回值类型的字符串
const char * method_getTypeEncoding ( Method m );
// 获取方法的返回值类型的字符串
char * method_copyReturnType ( Method m );
// 获取方法的指定位置参数的类型字符串
char * method_copyArgumentType ( Method m, unsigned int index );
// 通过引用返回方法的返回值类型字符串
void method_getReturnType ( Method m, char *dst, size_t dst_len );
// 返回方法的参数的个数
unsigned int method_getNumberOfArguments ( Method m );
// 通过引用返回方法指定位置参数的类型字符串
void method_getArgumentType ( Method m, unsigned int index, char *dst, size_t dst_len );
// 返回指定方法的方法描述结构体
struct objc_method_description * method_getDescription ( Method m );
// 设置方法的实现
IMP method_setImplementation ( Method m, IMP imp );
// 交换两个方法的实现
void method_exchangeImplementations ( Method m1, Method m2 );
方法调用流程
在Objective-C中,消息直到运行时才绑定到方法实现上。编译器会将消息表达式[receiver message]转化为一个消息函数的调用,即objc_msgSend。这个函数将消息接收者和方法名作为其基础参数