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]]; } @endI'm now a carefree convert to invocations, as I can simply do this:
button.action = [NSInvocation invocationWithTarget:self selector:@selector(browseURL:) argument:url];