What's the purpose of the setSelector method on the NSInvocation class?
Asked Answered
A

3

10

I don't understand why we have to call the setSelector method on NSInvocation objects when that information is already passed via the invocationWithMethodSignature.

To create an NSInvocation object we do the following:

SEL someSelector;
NSMethodSignature *signature;
NSInvocation *invocation;

someSelector = @selector(sayHelloWithString:);

//Here we use the selector to create the signature
signature = [SomeObject instanceMethodSignatureForSelector:someSelector];
invocation = [NSInvocation invocationWithMethodSignature:signature];

//Here, we again set the same selector
[invocation setSelector:someSelector];
[invocation setTarget:someObjectInstance];
[invocation setArgument:@"Loving C" atIndex:2];

Notice that we passed the selector to [SomeObject instanceMethodSignatureForSelector: someSelector]; and again to [invocation setSelector:someSelector];.

Is there something I'm missing?

Avertin answered 7/4, 2011 at 18:58 Comment(2)
+1 - Good to see a question here that hasn't been asked (and answered) a million times already, and isn't written in indecipherable instant-message jargon. :-)Unbalance
One small point: signature = [SomeObject instanceMethodSignatureForSelector:someSelector]; should be either signature = [[SomeObject class] instanceMethodSignatureForSelector:someSelector]; or signature = [SomeObject methodSignatureForSelector:someSelector];Terceira
P
8

A signature is not a selector. A selector is the name of a message. The signature defines the parameters and the return value. You can have many selectors with the same signature, and vice versa. If you look at NSMethodSignature, you will note that there is no -selector method; signatures do not carry around a particular selector.

Consider the following

- (void)setLocation:(CGFloat)aLocation;
- (void)setLocation:(MyLocation*)aLocation;

They have the same selector @selector(setLocation:), but different signatures.

- (void)setX:(CGFloat)x;
- (void)setY:(CGFloat)y;

These have the same signature, but different selectors.

Selectors from the ObjC Programming Language may be a useful reference for understanding this.

Planometer answered 7/4, 2011 at 19:13 Comment(2)
Whilst I get what you are saying, there seems to be a bit of redundancy in the language. I am setting the selector twice (once in the signature, and once again on the invocation instance). I personally (IMHO) think it'd be more efficient to either derive the selector (which in my case was defined in someSelector) from the signature.Avertin
You can't derive a selector from a signature. You can derive a signature from a target and a selector by asking the target (remember, new methods and classes can be created at runtime; you can't determine any of this at compile time). You're right that there could be +invocationWithTarget:selector:arguments: shortcut method (my team has a category that adds something similar). It wouldn't be more efficient since it would just call the code you're calling, but it would be a little more convenient.Planometer
U
3

A method signature only defines the return type, and the number and type of arguments. It doesn't include anything about the selector name. For example, all of these methods have the same signature, despite having different selectors:

-(void) foo:(NSString*)fooString;
-(void) bar:(NSString*)barString;
-(void) baz:(NSString*)bazString;
Unbalance answered 7/4, 2011 at 19:14 Comment(0)
T
0

This is kind of a side-answer, but the fact that you can do the following helped me understand better the separation between method signatures and selectors.

This code is within a View Controller

NSMethodSignature *sig = nil;
sig = [[self class] instanceMethodSignatureForSelector:@selector(viewDidAppear:)];
NSInvocation *myInvocation = nil;
myInvocation = [NSInvocation invocationWithMethodSignature:sig];

[myInvocation setTarget:_somePopoverController];
[myInvocation setSelector:@selector(dismissPopoverAnimated:)];
BOOL animate = YES;
[myInvocation setArgument:&animate atIndex:2];
[myInvocation invoke];

Since UIViewController's viewDidAppear: and UIPopoverController's dismissPopoverAnimated: both take a BOOL argument and return void, you can create the method signature using one selector, but send the invocation to another.

Terceira answered 26/5, 2011 at 10:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.