必威体育Betway必威体育官网
当前位置:首页 > IT技术

performSelector调用和直接调用的区别

时间:2019-09-29 21:13:22来源:IT技术作者:seo实验室小编阅读:80次「手机版」
 

performselector

原文链接: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.

相关阅读

typedef和define有什么区别

typedef和define都是替一个对象取一个别名,以此增强程序的可读性,区别如下:(1)原理不同#define是C语言中定义的语法,是预处理指令,在预处

windows RT开发笔记:WinRT DLL及其调用研究

一. 几个概念:WinRT :Windows Runtime, windows运行时。创建Windows运行时(WinRT)是为了在Windows上给用户提供一种流畅且安全的应用

推荐几款可以直接在手机上编程的app(包含Java、C、Pyt

这里介绍几款可以在手机上编程的app,分别是: 1.java和Android:AIDE集成开发环境。 2.C语言:c语言编译器、C4droid。 3.python:QPyth

Java中notify和notifyAll的区别 - 何时以及如何使用

Java  notify   vs notifyAll   notify和notifyAll方法之间有什么区别是棘手的Java问题之一! Condition 是个什么玩

华为荣耀盒子voice与华为盒子/荣耀盒子有什么相同与区

荣耀新发布的智能语音4K盒子-荣耀盒子voice,与上一代荣耀盒子、华为盒子和秘盒有什么区别呢?该如何根据自己的需求购买盒子呢?一、接

分享到:

栏目导航

推荐阅读

热门阅读