在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. 《第一本docker书》第4章 使用docker镜像和仓库 读书笔记

    docker最底端是一个引导文件系统,即bootfs. 第二层是root文件系统rootfs,位于引导文件系统之上. 在传统的Linux引导过程中,root文件系统会最先以只读的方式加载,当引导结束并 ...

  2. HTML 方法

    姓名输入框:<input type="text" value="默认有值"/> 密码输入框:<input type="text&qu ...

  3. java方法参数

    Java程序设计语言总是采用值调用.也就是说,方法得到的是所有参数的一个拷贝,特别是方法不能修改传递给它的任何参数变量的内容. 基本类型参数 1)X被初始化为percent值的一个拷贝: 2)X被乘以 ...

  4. 使用 Jasmine 进行测试驱动的 JavaScript 开发

    Jasmine 为 JavaScript 提供了 TDD (测试驱动开发)的框架,对于前端软件开发提供了良好的质量保证,这里对 Jasmine 的配置和使用做一个说明. 目前,Jasmine 的最新版 ...

  5. oracle的存储过程和函数(PL/SQL)

    czmmiao 存储过程概述 存储过程是子程序的一种类型,能够完成一些任务,作为schema对象存储于数据库.是一个有名字的PL/SQL代码块,支持接收或不接受参数,同时也支持参数输出.一个存储过程通 ...

  6. 如何让popWindow显示在view上方

    看了bilibili的客户端搜索按钮,很喜欢大爱!自己也想做个类似的(相似度 10% 哈哈) popWin的出现退出动画也可以自己设定,用过其方法setAnimationStyle(R.style.x ...

  7. 饮水思源——python中常用基础类源码解析

    1.bool类 2.int类 3.long类 4.float类 5.str类 6.list类 7.tuple类 8.dict类 9.collections类 Counter类:为hashable对象计 ...

  8. vuex是啥

    vuex是一个状态管理工具. vuex store与一个简单的全局变量的区别是: 1.vuex stores 是响应式的,当组件改变state时,它能响应并高效地更新state. 2.state不能被 ...

  9. hadoop输入格式(InputFormat)

    InputFormat接口(package org.apache.hadoop.mapreduce包中)里包括两个方法:getSplits()和createRecordReader(),这两个方法分别 ...

  10. Visual Studio 拓展插件——Image Optimizer

    一句话概括效用:在Visual Studio的解决方案中,为图片或包含图片的文件夹添加右键菜单,可对图片进行压缩,无损压缩. 在VS扩展工具中安装 安装好后在VS资源管理器中选择图片右键,在右键菜单中 ...