使用[self method]或@selector(method)?

fuz*_*oat 10 iphone cocoa-touch objective-c

任何人都可以告诉我下面两个陈述之间的差异.

[self playButtonSound];
Run Code Online (Sandbox Code Playgroud)

和:

[self performSelector:@selector(playButtonSound)];
Run Code Online (Sandbox Code Playgroud)

我只是问,因为我有一些使用过的旧代码@selector,现在有了更多的知识,我想不出为什么我没有使用[self playButtonSound],他们似乎都像在这里写的一样.

加里

Ste*_*son 11

两者都是相同的,但[self playButtonSound];绝对是在Objective-C中调用方法的常规方法.但是,using performSelector:允许您调用仅在运行时确定的方法.

来自NSObject协议参考:

所述performSelector:方法等同于发送aSelector 直接消息发送到所述接收器.例如,以下所有三条消息都执行相同的操作:

id myClone = [anObject copy];
id myClone = [anObject performSelector:@selector(copy)];
id myClone = [anObject performSelector:sel_getUid("copy")];
Run Code Online (Sandbox Code Playgroud)

但是,该performSelector:方法允许您发送在运行时之前未确定的消息.变量选择器可以作为参数传递:

SEL myMethod = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector:myMethod];
Run Code Online (Sandbox Code Playgroud)


Vla*_*mir 6

[self playButtonSound]; 
Run Code Online (Sandbox Code Playgroud)

这里编译器将检查您的对象是否响应-playButtonSound消息,如果不响应则会给出警告.

[self performSelector:@selector(playButtonSound)];
Run Code Online (Sandbox Code Playgroud)

-playButtonSound这种方式调用您将不会收到编译器警告.但是,您可以动态检查对象是否响应给定的选择器 - 这样您就可以安全地尝试在对象上调用任意选择器而不指定其类型并且不会收到编译器警告(这可能对于调用对象委托中的可选方法很有用) :

if ([self respondsToSelector:@selector(playButtonSound)])
  [self performSelector:@selector(playButtonSound)];
Run Code Online (Sandbox Code Playgroud)

  • 实际上,通过在构建设置的"其他警告标志"字段中添加-Wundeclared-selector,可以让编译器在未声明的选择器中发出警告.我觉得这很有帮助. (2认同)