您的位置:首页 > 其它

performSelector调用和直接调用的区别

2016-10-05 17:48 323 查看


原文链接: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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  performSelector