Class 类型、Selector 选择器、SEL 类型、函数指针
一、Class 类型
-
机制:一个类在正确编译后,在这个被正确编译好的类里面,存在一个isa指针,用于存储类的方法及变量信息,这个isa指针是id类型。可以通过一个普通的字符串可能获取到这个Class类型对象,也可以通过此类的对象获取到此类的Class类型对象,获取到Class类型对象后,可以按类实例化后的对象一样使用它。在程序runtime可以通过类的Class类型对象获取到类实例化后的对象,也可以动态的获取在编译阶段无法确定的对象。
-
因为,在类里面存储了类的所有信息,所以,可以通过类的名称或类的对象获取到Class类型对象。当然,也可以获取到超类的Class类型对象。
1 // 通过类名称或对象,向此类或者对象发送class消息,获取此类的Class类型对象 2 Class class = [类名称或对象 class]; 3 // 通过类名称或对象,向此类或者对象发送superclass消息,获取此类的超的Class类型对象 4 Class superClass = [类名称或对象 superclass]; 5 // 通过类名称字符串,获取此类的Class类型对象 6 Class class = NSClassFromString(类名称字符串); 7 // 通过Class类型对象,获取此类的名称字符串 8 NSString *classname = NSStringFromClass(Class 参数); 9 // 向类对象发送消息,获取类的类名称,classname是一个固定参数,详细参考classname实现源码 10 NSString *classname = [classobject classname];
二、Selector 选择器
-
机制:选择器Selector是用于表示方法的,会根据方法的名称(参数序列),确定一个唯一的身份证明(其实,就是一个整数),(摸不准/*在不同的类里面相同名称相同声明的方法,其身份证明是相同的)。在runtime就不用对方法的名称进行比较,以确定要执行的是哪一个方法,只要通过一个整数就可以定位到相应的方法,然后就可以找到相应方法的入口地址,就可以执行方法了。在OC中消息的执行(方法的执行)与C语言直接找到函数地址入口方式相比,OC的消息机制从效率上讲是比较低下的。虽然,OC使用了Selector选择等方式进行寻找,总是要花费时间的。OC是兼容C语言的,也就是说可以使用C的函数指针方式,增加效率。当要求效率时,比如,当在一个大循环里,要使用某一功能时,就放弃对某一单一对象发送消息的方式(Selector),从而使用函数指针,这样就有和C一样的效率了。
三、SEL 类型
- 在Selector选择器已经说了,在编译的时候,会根据方法的名字及参数序列,确定一个唯一的身份证明,这个身份证明就是一个SEL类型,可以通过方法名字取得方法的ID(SEL类型对象),也可以通过方法名称的字符串取得SEL类型对象。反之,也可以通过SEL类型对象(ID)取得方法名字。如下:
1 // 通过方法名称,获取此方法的SEL类型对象 2 SEL 变量名 = @selector(方法名称); 3 // 通过方法名称字符串,获取此方法的SEL类型对象 4 SEL 变量名 = NSSelectorFromString(方法名称字符串); 5 // 通过方法的SEL类型对象及参数,获取方法名称 6 NSString *变量名 = NSStringFromSelector(SEL 参数); 7 // 通过SEL类型对象,获取到此方法的方法名称 8 NSString *变量名 = [SEL methodname];
- 调用方式
1 // 对象 -- 接收器 2 [对象 performSelector: SEL类型变量 withObject: 参数1 withObject: 参数2 ...];
- 好处:增加其方法使用的灵活性,可以通过配置文件(文本文件、XML文件)指定程序要执行的方法,在runtime读取配置文件,将方法名称或方法名称字符串转换成SEL类型对象,通过发送消息执行。由于,OC中寻找方法是通过ID(一个整型值),相比匹配字符串寻找方法要有效率得多。
四、函数指针
- 格式
1 // C函数指针,id -- 接收者对象,SEL -- 方法的SEL类型对象,NSString * -- 方法参数(自定义) 2 void (*func)(id, SEL, NSString *); 3 // OC 4 IMP funoc;
PS: 用法和C一样。
- 例子
1 id cla = [[ClassE alloc] init]; 2 SEL funoc = @Selector(fun); 3 void (*func)(id, SEL, NSString *); 4 func = (id, SEL, NSString *) [cla methodForSelector: funoc]; 5 func(cla, funoc, @"test");
- 参数 (在OC中,函数指针的前两个参数,即:id与SEL是必须的,剩下的参数是由函数指针的参数序列决定)
- id -- 是一个id类型,是指消息的接收者对象。在runtime实际上id就是self对象,因为要从某个对象发送消息。
- SEL -- 是一个SEL类型,是指方法的ID(方法的身份证明,一个整型),在消息发送过程中,通过_cmd方法本身的SEL(方法ID)。也就是说在方法的定义体里面,可以通过_cmd获取方法本身的ID。
- NSString* -- 自定义参数。