今天在准备出笔试题的过程中随便搜了一下其他的笔试题,看到其中一个就是关于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. 连接远程docker内的mysql(navicat)

    拉取mysql镜像 docker pull mysql:5.6 查看mysql镜像 docker images | grep mysql 启动mysql容器 docker run -p 3306:33 ...

  2. JAVA:windows myeclipse jdk tomcat maven 完美搭建

    文章来源:http://www.cnblogs.com/hello-tl/p/8305027.html 0.下载所需安装包 jdk-7u71-windows-x64.exe   链接:http://p ...

  3. windows下安装oracle客户端和php扩展

    先来抱怨下 ,按这玩楞费了我大半天的时间,一路的坑! 我的电脑是win7 64位的 第一步  打开php.ini  把 extension=php_oci8_12c.dll extension=php ...

  4. 我的Python分析成长之路1

    Python是什么?                                                                                           ...

  5. 【C#】【数据结构】005-栈:顺序栈

    C#数据结构:顺序栈 1.自定义顺序栈结构: /// <summary> /// 顺序栈 /// </summary> /// <typeparam name=" ...

  6. FZU- Problem 1147 Tiling,递推坑题,大数水过~~

    Problem 1147 Tiling Time Limit: 1000 mSec Memory Limit : 32768 KB http://acm.fzu.edu.cn/problem.php? ...

  7. MVC4 上传图片并生成缩略图

    Views @using (Html.BeginForm("Create","img",FormMethod.Post, new { enctype = &qu ...

  8. [codeforces551E]GukiZ and GukiZiana

    [codeforces551E]GukiZ and GukiZiana 试题描述 Professor GukiZ was playing with arrays again and accidenta ...

  9. POJ 2375 Cow Ski Area【tarjan】

    题目大意:一个W*L的山,每个山有个高度,当且仅当一个山不比它相邻(有公共边的格子)的山矮时能够滑过去,现在可以装化学电梯来无视山的高度滑雪,问最少装多少电梯使得任意两点都可到达 思路:最后一句话已经 ...

  10. hdu 2845

    #include<stdio.h> #define N 200100 int f[N]; int  a[N],n; int main() { int m,j,i,suma,sumb,sum ...