简体   繁体   中英

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

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?

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.

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;

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM