NSInvocation wraps everything that's needed for a selector invocation: the target object, the selector, the arguments and even the result. However, there's a lot of boilerplate code required to set one up, which is one of the reasons it eluded me for so long:
SEL selector = @selector(mySelector:); NSString *argument = @"Hello World!"; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector:selector]]; [invocation setTarget:self]; [invocation setSelector:selector]; [invocation setArgument:&argument atIndex:2]; [invocation retainArguments];Note that the first argument is at index 2, since
self and _cmd are passed implicitly. I also make the invocation retain its argument to make it self-contained.Now you can pass the invocation to any other object who only needs to invoke it:
[invocation invoke];Having found a life-saving use for this construct, I set out to make life easier for myself:
@implementation NSInvocation (VikramsOneLineConstructors)
+ (NSInvocation *)invocationWithTarget:(id)target selector:(SEL)selector
arguments:(NSArray *)arguments {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
[target methodSignatureForSelector:selector]];
[invocation setTarget:target];
[invocation setSelector:selector];
for (NSInteger i = 0; i < [arguments count]; i++) {
id argument = [arguments objectAtIndex:i];
[invocation setArgument:&argument atIndex:2+i];
}
[invocation retainArguments];
return invocation;
}
+ (NSInvocation *)invocationWithTarget:(id)target selector:(SEL)selector argument:(id)argument {
return [NSInvocation invocationWithTarget:target selector:selector arguments:[NSArray arrayWithObject:argument]];
}
@end
I'm now a carefree convert to invocations, as I can simply do this:button.action = [NSInvocation invocationWithTarget:self selector:@selector(browseURL:) argument:url];