如何在Objective C中的块中应用参数列表?

时间:2011-10-13 20:09:27

标签: objective-c objective-c-blocks apply

Objective C是否具有类似Smalltalk的Block valueWithArguments

的功能

我正在寻找一个带有签名的函数:

apply(^(), NSArray* args)

或者,有没有办法在参数列表上调用选择器?

2 个答案:

答案 0 :(得分:2)

NSArray方法enumerateObjectsUsingBlock:enumerateObjectsWithOptions:usingBlock:是您要找的?

[[NSArray arrayWithObjects:@"a", @"b", @"c", nil]
 enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  NSLog(@"%d: %@", idx, obj);
}];

答案 1 :(得分:2)

使用块你可能需要做一些va_args魔术。可以使用可变参数调用选择器,但是你可能想要一些助手来减轻它的痛苦。

NSObject的+ performSelectorWithArgsArray.h

@interface NSObject (performSelectorWithArgsArray)
- (id)performSelector:(SEL)sel withArgsArray:(NSArray *)args;
@end

NSObject的+ performSelectorWithArgsArray.m

@implementation NSObject (performSelectorWithArgsArray)
- (id)performSelector:(SEL)sel withArgsArray:(NSArray *)args {
  NSInvocation *inv = [NSInvocation invocationWithMethodSignature:
                       [self methodSignatureForSelector:sel]];
  [inv setSelector:sel];
  [inv setTarget:self];
  for (int i = 0; i < args.count; i++) {
    id a = [args objectAtIndex:i];
    [inv setArgument:&a atIndex:2 + i]; // 0 is target, 1 is cmd-selector
  }
  [inv invoke];

  NSNumber *r;
  [inv getReturnValue:&r];
  return r;
}
@end

然后像这样使用它:

#import "NSObject+performSelectorWithArgs.h"

@interface SomeClass : NSObject
@end

@implementation SomeClass
- (NSNumber *)withA:(NSNumber *)a withB:(NSNumber *)b {
  return [NSNumber numberWithInt:a.intValue + b.intValue];
}
@end

- (void)someMethod {
  SomeClass *a = [[SomeClass alloc] init];
  SEL sel = @selector(withA:withB:);
  NSArray *args = [NSArray arrayWithObjects:
                   [NSNumber numberWithInt:2],
                   [NSNumber numberWithInt:3],
                   nil];
  NSNumber *r = [a performSelector:sel withArgsArray:args];
  NSLog(@"%d", r.intValue);
}

如果你选择做这样的事情,我建议你真正了解NSInvocation的工作方式,因为它可以咬得很厉害。不确定是否可以这样做而不要求所有参数和返回值都是对象。