performSelector调用和直接调用的区别

来源:互联网 发布:小米电视 电视直播软件 编辑:程序博客网 时间:2024/04/29 03:16

原文链接:http://www.cnblogs.com/agger0207/p/4426131.html

performSelector调用和直接调用的区别

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

0 0
原创粉丝点击