在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返回一个选择器对应的方法名称:

  1. NSString * method;
  2. method = NSStringFromSelector(setWidthHeight);

 

方法和选择器

编译的选择器是以方法名称为区分的,而不是以方法的实现。一个类中的display方法的选择器和另外类中的display方法的选择器是同一个。这点对于多态性和动态绑定来说是非常重要的。这使得我们可以为不同类的对象发送相同的消息。如果不同的方法实现对应的是不同的选择器,那么消息和函数调用将没有什么区别。相同名称的类方法和实例方法对应的选择器也是同一个。然后由于两者的作用域是不同的,因此这不会造成冲突。一个类中是可以同时定义display类方法和display实例方法的。

方法的返回值及其参数的类型

        发送消息的例行程序只有通过选择器才能访问方法的实现。因此,它处理所有相同名称的方法的选择器的方式是一样的。它能够从选择器中判断方法的返回值及其参数的类型。因此,除了向静态类型的接收者发送消息之外,动态绑定要求所有名称相同的方法必须具有相同的返回值和参数类型。(静态类型的接收者是个例外,因为在编译时就可以从对应的类中感知到方法的具体实现。)

尽管名称完全一样的类方法和实例方法拥有相同的选择器,它们的参数和返回值的类型可以是不同的。

运行时发送可变消息

NSObject协议中定义的performSelector:,performSelector:WithObject:,performSelector:withObject:withObject:方法都是接收一个SEL类型的变量作为其第一个参数。这三个方法都是直接把消息映射为对应的函数。例如:[friend performSelector:@selector(gossipAbout:) withObject:aNeighbot];和下面的语句是等价的:[friend gossipAbout:aNeighbot];上面的三个方法使得我们可以再运行时发送不同的消息。这正如和运行时接收消息的对象是可变的一样。在发送消息的表达式中,接收者和消息都可以是变量:

  1. id helper = getTheReceiver();
  2. SEL request = getTheSelector();
  3. [helper performSelector:request];

在上面的示例程序中,接收者(helper)是在运行时通过一个假定的函数getTheReceiver而动态选择的;要执行的方法(request)同样也是在运行时通过函数getTheSelector来动态决定的。

译者注:从上面的示例中可以看出,接收消息的对象和发送的具体消息在运行时都是可变的。所以可变消息指的就是上面的这种可变性,而不仅仅局限于发送的消息是可变的。

注意:

performSelector:及其他的方法的返回值类型都是id。如果执行方法的返回值类型不是id类型,则应该对其进行适当的转换。强制的类型转换并不是对所有类型都适用的。执行方法的返回值应该是指针或者是和指针相兼容的类型。

SEL方法选择器的更多相关文章

  1. ios runtime部分事例方法说明

    一.场景--动态改变变量 unsigned ; Ivar *ivar = class_copyIvarList([self.person class], &count); ; i<cou ...

  2. SEL-消息机制

    int main() { Person *p = [[Person alloc] init]; //调用方法 [p test2]; [p performSelector:@selector(test2 ...

  3. Objective-C总Runtime的那点事儿(一)消息机制

    最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎必问,例 如:RunLoop,Block,内存管理等.其他的问题 ...

  4. iOS运行时Runtime浅析

    运行时是iOS中一个很重要的概念,iOS运行过程中都会被转化为runtime的C代码执行.例如[target doSomething];会被转化成objc)msgSend(target,@select ...

  5. Effective Objective-C 2.0 学习记录

    由于最近入职,公司安排自由学习,于是有时间将Effective Objective-C 2.0一书学习了一遍.由于个人知识面较窄,对于书中有些内容无法理解透彻,现将所学所理解内容做一遍梳理,将个人认为 ...

  6. oc - runtime运行机制

      Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时做的事放到了运行时来处理.同时OC也是一门简单的语言,很大一部分是C的内容,只是在语言层面上加了关键字和语法,真正让OC强大 ...

  7. Objective-C总Runtime的那点事儿(一)消息机制【转】

    RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何 ...

  8. iOS开发:详解Objective-C runTime

    Objective-C总Runtime的那点事儿(一)消息机制 最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎 ...

  9. runtime--小白看过来

    目录 RunTime 概述 RunTime消息机制 RunTime交换方法 RunTime消息转发 RunTime关联对象 RunTime实现字典与模型互转 1.RunTime 概述 我们在面试的时候 ...

随机推荐

  1. LTE Module User Documentation(翻译9)——Using the EPC with emulation mode

    LTE用户文档 (如有不当的地方,欢迎指正!) 15 Using the EPC with emulation mode(使用仿真方式的 EPC)     在上一节中,我们使用点对点链路连接基站和服务 ...

  2. java高薪之路__001_类

    Java中内部类分四种:成员内部类.局部内部类.静态内部类和匿名内部类.要注意静态内部类的调用方式与其他不同,采用的是类似调用类中的静态属性.静态方法的方式 Multi Level 调用不同类中的相同 ...

  3. 使用easyui时 进入一个新页面 前要经过一个页面混乱的时候 才到正常的页面去

    var width = $(window).width(); var height = $(window).height(); var html = "<div id='loading ...

  4. 解决:Unknown table engine 'InnoDB'

        把查询mysql的结果输出到文件的过程中出现了错误 ERROR 1286 (42000): Unknown table engine 'InnoDB'     这个问题的原因是新版mysql是 ...

  5. python中requests

    #发送无参数的get请求import requests def get_html(url): res = requests.get(url) return res.text #发送无参数的post请求 ...

  6. JVM实用参数——新生代垃圾回收

    JVM实用参数目录 JVM实用参数——新生代垃圾回收 概述 第1部分  新生代垃圾回收介绍 第2部分 参数介绍 参考 第1部分  新生代垃圾回收介绍 本部分,我们将关注堆(heap) 中一个主要区域, ...

  7. MyBatis关联查询 (association) 时遇到的某些问题/mybatis映射

    先说下问题产生的背景: 最近在做一个用到MyBatis的项目,其中有个业务涉及到关联查询,我是将两个查询分开来写的,即嵌套查询,个人感觉这样更方便重用: 关联的查询使用到了动态sql,在执行查询时就出 ...

  8. Useful blogs

    Unofficial Windows Binaries for Python Extension Packages:http://www.lfd.uci.edu/~gohlke/pythonlibs ...

  9. iOS开发UI篇—在UITableview的应用中使用动态单元格来完成app应用程序管理界面的搭建

    iOS开发UI篇—在UITableview的应用中使用动态单元格来完成app应用程序管理界面的搭建 一.实现效果 说明:该示例在storyboard中使用动态单元格来完成. 二.实现 1.项目文件结构 ...

  10. Halcon 10.0 Sample:完整性检查(圆形)

    * ball.hdev: Inspection of Ball Bonding * 球接合检查 Comment Time:// *核心思想:.白色区域用作自动ROI,黑色区域是目标 * .Openin ...