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];
 
No comments:
Post a Comment