今天在准备出笔试题的过程中随便搜了一下其他的笔试题,看到其中一个就是关于performSelector与直接调用的区别。

个人感觉这其实是一个陷阱题,因为大部分应用场景下,用哪一种都可以,可以说是没有区别的,但其实又有一些细节上的区别。

比如说,假如有如下代码:

- (void)doTest {

    Student* student = [[Student alloc] init];

    [student performSelector:@selector(doSomething)];

    [student doSomething];

}

具体执行过程中的区别道理是什么呢?

还是先看官方文档对performSelector的描述:

- (id)performSelector:(SEL)aSelector

Description

Sends a specified message to the receiver and returns the result of the message. (required)

The performSelector: method is equivalent to sending an aSelector message directly to the receiver. For example, all three of the following messages do the same thing:

id myClone = [anObject copy];

id myClone = [anObject performSelector:@selector(copy)];

id myClone = [anObject performSelector:sel_getUid("copy")];

However, the performSelector: method allows you to send messages that aren’t determined until runtime。 A variable selector can be passed as the argument:

SEL myMethod = findTheAppropriateSelectorForTheCurrentSituation();

[anObject performSelector:myMethod];

The aSelector argument should identify a method that takes no arguments. For methods that return anything other than an object, use NSInvocation.

核心的就那么几句:

1 执行的效果其实和发送消息是等价的;

2 performSelector允许发送未在运行时确定的消息;也就是说,只要这个消息能够被转发到正确的接收者,能够被最后的接收者识别,都是可以正确运行的。否则,就会在运行时报错“unrecognized selector sent to instance”.

具体来说:假如上面的Student的定义和实现如下:

@interface Student : NSObject

- (void)doSomething;

@end

@implementation Student

- (void)doSomething {

    NSLog(@"doSomething");

}

@end

那么这两者基本上是等价的;但是,假如doSomething是一个私有的方法呢? 可以试着将这个方法从头文件中删除如下:

@interface Student : NSObject

@end

这个时候[student doSomething];就会在编译时候报错啦!

而对于performSelector呢,仅仅当编译警告选项“Undeclared Selector”打开的时候才会有编译警告。

另外,即使这个方法并没有实现,也就是说从.m文件中删除这个方法,编译是可以通过的,但是运行时会Crash,报的错误就是刚才的“unrecognized selector sent to instance”.

我自己由于是从C++程序员转过来的,所以其实更喜欢[student doSomething]这种方法,一旦有问题的时候,在编译期间就很容易发现啦!

但Obejct-C的动态特性是允许在运行时向某个类添加方法的,这个时候就一定需要使用performSelector了。那么为了避免运行时出现错误,在使用performSelector之前一定要使用如下的检查方法来进行判断。

- (BOOL)respondsToSelector:(SEL)aSelector;

The End.

performSelector调用和直接调用的区别的更多相关文章

  1. oracle创建函数和调用存储过程和调用函数的例子(区别)

    创建函数: 格式:create or replace function func(参数 参数类型) Return number Is Begin --------业务逻辑--------- End; ...

  2. 调用run与调用start的区别

    调用start的结果 package TestException; public class test1 { public static void main(String[] args) { // 3 ...

  3. MFC OnPaint()函数中最先调用CDialog::OnPaint()和最后调用CDialog::OnPaint()的巨大区别

    OnPaint()函数中最先调用CDialog::OnPaint()和最后调用CDialog::OnPaint()的巨大区别,如果没有注意这个问题就会出现无厘头式的绘图问题-- 效果就是出不来!在经过 ...

  4. 转 - RPC调用和HTTP调用的区别

    很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单 ...

  5. RPC调用和HTTP调用的区别

    很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单 ...

  6. 反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)

    反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性.字段),而不去使用Invoke方法)   创建Delegate (1).Delegate.CreateDelegate(Type, ...

  7. C#“同步调用”、“异步调用”、“异步回调”

    本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: ); //模拟该方法运 ...

  8. C++调用DLL有两种方法——静态调用和动态调用

    C++调用DLL有两种方法——静态调用和动态调用 标签: dllc++winapinullc 2011-09-09 09:49 11609人阅读 评论(0) 收藏 举报  分类: cpp(30)  [ ...

  9. dll静态调用和动态调用

    动态链接库有2种连接方式,一种是通过库直接加入(又叫隐式加载或载入时加载),一种是在运行时加入.后者很好理解,比如LoadLibrary(),GetProcAddress()获取想要引入的函数,使用完 ...

  10. C#(同步调用、异步调用、异步回调)

    Review: 原作者虽然使用了汉字的类名,看起来十分蹩脚,但是,还是把同步调用.异步调用.异步回调的使用讲解的很详细的.原理讲解的很清晰. ------ 本文将主要通过“同步调用”.“异步调用”.“ ...

随机推荐

  1. The MySQL server is running with the –secure-file-priv

    show variables like '%secure%'; 将文件导出路径更改为查询到的secure-file-priv路径下 select * from table where column = ...

  2. ios之数据持久化

    9.1 数据持久化概述 iOS中可以有四种持久化数据的方式: 属性列表.对象归档.SQLite3和Core Data 9.2 iOS应用程序目录结构 iOS应用程序运行在Mac os模拟器时候,有一下 ...

  3. 02numpy

    一. Numpy定义 一个在Python中做科学计算的基础库,重在数值计算,也是大部分PYTHON科学计算库的基础库,多用于在大型.多维数组上执行数值运算 二. Numpy使用 1.创建数组 2.nu ...

  4. 【2018 CCPC网络赛】1003 - 费马小定理

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6440 这题主要是理解题意: 题意:定义一个加法和乘法,使得 (m+n)p = mp+np; 其中给定 ...

  5. curl 模拟post请求

    curl -H "Content-Type:application/json" -X POST --data '{"openId":"xxxxxxx& ...

  6. 第二讲:vcs debugging basics

    要求: 1.describe three methods of debugging verilog code using vcs 2.invoke ucli debugger(不重要) 3.debug ...

  7. day22 01 初识面向对象----简单的人狗大战小游戏

    day22 01 初识面向对象----简单的人狗大战小游戏 假设有一个简单的小游戏:人狗大战   怎样用代码去实现呢? 首先得有任何狗这两个角色,并且每个角色都有他们自己的一些属性,比如任务名字nam ...

  8. js的闭包中关于执行环境和作用链的理解

    首先讲一讲执行环境: 执行环境按照字面上来理解就是指目前代码执行所在的环境. 当JavaScript代码执行的时候,会进入不同的执行上下文,这些执行上下文会构成了一个执行上下文栈(Execution ...

  9. BeautifulSoup4系列一

    前言 以博客园为例,爬取我的博客上首页的发布时间.标题.摘要,本篇先小试牛刀,先了解下它的强大之处,后面讲beautifulsoup4的详细功能. 一.安装 1.打开cmd用pip在线安装beauti ...

  10. (二)java集合框架综述

    一集合框架图 说明:对于以上的框架图有如下几点说明 1.所有集合类都位于java.util包下.Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Ja ...