SEL方法选择器
在Objective-C中,选择器(selector)有两个意思。 一是指在代码中的方法的名称。二是指在编译是用于替换方法名称的唯一的标识符。编译后的选择器的为SEL类型。所有名称相同的方法拥有同一个选择器。通过使用选择器可以调用对象的一个方法。这是Cocoa中目标-动作这一模式能得以实现的基础。
方法和选择器
出于效率的考虑,编译后的代码中并不是使用ASCII码表示的方法名称来作为方法的选择器的。编译器会把每一个方法的名称写入到一张表中;然后用唯一的一个标识符与之结对,这样来表示运行时的方法。运行时系统确保了这种标识符的唯一性:不会出现相同的两个选择器;所有名称相同的方法有用唯一同一个选择器。
SEL和@selector
编译的选择器拥有一种特殊的类型:SEL,以便和其它的数据类型进行区分。有效的选择器都是非0值的。对SEL类型的赋值必须由系统进行;其他的赋值方式都是无益的。
指令@selector()表示使用编译的选择器,而不是完整的方法名称。如下,setWidth:height:的选择器被赋值给了setWidthHeight变量:
SEL setWidthHeight;
setWidthHiehgt = @selector(setWidth:height:);
在编译时使用@selector指令来给SEL类型的变量赋值是效率最高的。然而,在某些情况下,可能需要将字符串转换成运行时的选择器。此时可以使用NSSelectorFromString函数来完成:
setWidthHeight = NSSelectorFromString(aBuffer);
反向的转换也是可以的。函数NSStringFromSelector返回一个选择器对应的方法名称:
- NSString * method;
- method = NSStringFromSelector(setWidthHeight);
方法和选择器
编译的选择器是以方法名称为区分的,而不是以方法的实现。一个类中的display方法的选择器和另外类中的display方法的选择器是同一个。这点对于多态性和动态绑定来说是非常重要的。这使得我们可以为不同类的对象发送相同的消息。如果不同的方法实现对应的是不同的选择器,那么消息和函数调用将没有什么区别。相同名称的类方法和实例方法对应的选择器也是同一个。然后由于两者的作用域是不同的,因此这不会造成冲突。一个类中是可以同时定义display类方法和display实例方法的。
方法的返回值及其参数的类型
发送消息的例行程序只有通过选择器才能访问方法的实现。因此,它处理所有相同名称的方法的选择器的方式是一样的。它能够从选择器中判断方法的返回值及其参数的类型。因此,除了向静态类型的接收者发送消息之外,动态绑定要求所有名称相同的方法必须具有相同的返回值和参数类型。(静态类型的接收者是个例外,因为在编译时就可以从对应的类中感知到方法的具体实现。)
尽管名称完全一样的类方法和实例方法拥有相同的选择器,它们的参数和返回值的类型可以是不同的。
运行时发送可变消息
NSObject协议中定义的performSelector:,performSelector:WithObject:,performSelector:withObject:withObject:方法都是接收一个SEL类型的变量作为其第一个参数。这三个方法都是直接把消息映射为对应的函数。例如:[friend performSelector:@selector(gossipAbout:) withObject:aNeighbot];和下面的语句是等价的:[friend gossipAbout:aNeighbot];上面的三个方法使得我们可以再运行时发送不同的消息。这正如和运行时接收消息的对象是可变的一样。在发送消息的表达式中,接收者和消息都可以是变量:
- id helper = getTheReceiver();
- SEL request = getTheSelector();
- [helper performSelector:request];
在上面的示例程序中,接收者(helper)是在运行时通过一个假定的函数getTheReceiver而动态选择的;要执行的方法(request)同样也是在运行时通过函数getTheSelector来动态决定的。
译者注:从上面的示例中可以看出,接收消息的对象和发送的具体消息在运行时都是可变的。所以可变消息指的就是上面的这种可变性,而不仅仅局限于发送的消息是可变的。
注意:
performSelector:及其他的方法的返回值类型都是id。如果执行方法的返回值类型不是id类型,则应该对其进行适当的转换。强制的类型转换并不是对所有类型都适用的。执行方法的返回值应该是指针或者是和指针相兼容的类型。
SEL方法选择器的更多相关文章
- ios runtime部分事例方法说明
一.场景--动态改变变量 unsigned ; Ivar *ivar = class_copyIvarList([self.person class], &count); ; i<cou ...
- SEL-消息机制
int main() { Person *p = [[Person alloc] init]; //调用方法 [p test2]; [p performSelector:@selector(test2 ...
- Objective-C总Runtime的那点事儿(一)消息机制
最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎必问,例 如:RunLoop,Block,内存管理等.其他的问题 ...
- iOS运行时Runtime浅析
运行时是iOS中一个很重要的概念,iOS运行过程中都会被转化为runtime的C代码执行.例如[target doSomething];会被转化成objc)msgSend(target,@select ...
- Effective Objective-C 2.0 学习记录
由于最近入职,公司安排自由学习,于是有时间将Effective Objective-C 2.0一书学习了一遍.由于个人知识面较窄,对于书中有些内容无法理解透彻,现将所学所理解内容做一遍梳理,将个人认为 ...
- oc - runtime运行机制
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时做的事放到了运行时来处理.同时OC也是一门简单的语言,很大一部分是C的内容,只是在语言层面上加了关键字和语法,真正让OC强大 ...
- Objective-C总Runtime的那点事儿(一)消息机制【转】
RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何 ...
- iOS开发:详解Objective-C runTime
Objective-C总Runtime的那点事儿(一)消息机制 最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎 ...
- runtime--小白看过来
目录 RunTime 概述 RunTime消息机制 RunTime交换方法 RunTime消息转发 RunTime关联对象 RunTime实现字典与模型互转 1.RunTime 概述 我们在面试的时候 ...
随机推荐
- VPN连接错误800的解决办法
1,IP填错.2,防火墙太严.3,使用过别的VPN软件.4,服务器上服务里Protected Sqwerrage和Routing and Remote Access这两项是否启动.5,重启电脑,删除原 ...
- 简单SSM配置详解
SSM:spring+springMVC+Mybatis 学习网友的http://www.cnblogs.com/invban/p/5133257.html,并对其进行了详细的解说. 源码下载:htt ...
- hibernate中设置BigDeCimal的精度
@Column(precision = 12, scale = 2) 在MySQL数据库中的精度为:
- js之oop <二> 对象属性
js中对象属性可以动态添加和删除.删除对象属性用delete关键字. function obj(){ } var oo = new obj(); oo.a = "a"; oo.b ...
- hdu2296Ring(ac自动机+dp)
链接 dp[i][j]表示长度为i在节点J的时候的权值最大值,根据trie树转移一下就行,需要每次都取最小的,所以需要另开一数组保存字典序最小的状态. #include <iostream> ...
- oracle 之 函数
本次主题 青涩/色 函数的结束一定要使用return语句返回一个与声明匹配的值 --语法: create[or replace] function<函数名> [(参数列表)] return ...
- 6个html5页面适配iphone6的技巧
iphone6及iphone6plus已经出来一段时间了.很多移动端网站,以前写死body为320px的,现在估计也忙着做适配了. 大屏幕手机其实一直有,只是以前大家没怎么重视,移动端的H5页面大部分 ...
- 如何正确的将J2ee项目部署到Tomcat
如何正确的将J2ee项目部署到Tomcat 1.打开配置文件(我的如下:C:\Program Files\Apache Software Foundation\Tomcat 7.0\conf\serv ...
- Linux下使用autoconf 和 automake 编译简单的HelloWorld
使用过开源C/C++项目的同学都知道,标准的编译过程已经变成简单的三部曲:./configure /make/make install,使用起来很方便,不像平时自己写代码,要手写一堆复杂的makefi ...
- i.BIO方式的SSL通道流程
前面已经讲解了BIO通道的整体流程,对于SSL的流程是插在通道中的,在BIO通道的初始化的时候,根据Connector配置的SSLEnabled属性进行SSL的逻辑. 主要集中的位置在JIOEndpo ...