views:

180

answers:

2

Can anyone enlighten me as to the differences between the two statements below.

[self playButtonSound];

AND:

[self performSelector:@selector(playButtonSound)];

I am just asking as I had some old code that used @selector, now with a little more knowledge I can't think why I did not use [self playButtonSound] instead, they both seem to do the same as written here.

gary

+1  A: 

Both to the same thing, but [self playButtonSound]; is definitely the normal way to invoke a method in Objective-C. However, using performSelector: allows you to call a method that is only determined at runtime.

From the NSObject Protocol Reference:

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];
Steve Harrison
+1  A: 
[self playButtonSound]; 

Here compiler will check if your object responds to -playButtonSound message and will give you a warning if it does not.

[self performSelector:@selector(playButtonSound)];

Calling -playButtonSound this way you will not get compiler warning. However you can check dynamically if objects responds to a given selector - so you can safely attempt to call arbitrary selector on a object without specifying its type and not getting compiler warnings (that may be useful for example for calling optional methods in a objects delegate):

if ([self respondsToSelector:@selector(playButtonSound)])
  [self performSelector:@selector(playButtonSound)];
Vladimir
There's a missing bracket in the line `if ([self respondsToSelector:@selector(playButtonSound)]`—it should be `if ([self respondsToSelector:@selector(playButtonSound)])`.
Steve Harrison
Actually, you can have the compiler throw a warning at undeclared selectors by adding -Wundeclared-selector in the Other Warning Flags field in your build settings. I find this to be pretty helpful.
Brad Larson