variadic方法:检查参数是否为typedef'ed块

时间:2011-10-24 16:03:02

标签: objective-c

我在NSArray上创建了一个veriadic Category方法,将其过滤为带有给定块和键的字典

typedef BOOL (^TestBlock)(id element);
- (NSDictionary *)dictionaryByFilteringWithBlocksAndKeys:(TestBlock)firstBlock, id firstKey,... NS_REQUIRES_NIL_TERMINATION;

用法:

NSArray *array = [NSArray arrayWithObjects:@"a", @"aa", @"ab", @"cc", @"cd", @"dd", nil];
NSDictionary *dict = [array dictionaryByFilteringWithBlocksAndKeys:
                                    ^BOOL(id element) {return [element hasPrefix:@"a"];},@"a",
                                    ^BOOL(id element) {return [element hasPrefix:@"c"];},@"c", 
         nil];

它的效果非常好,但我想知道,如果一个给定的块(除了第一个块之外)有一个typedef的签名,我该如何检查。

我使用va_listTestBlock block = va_arg(args, TestBlock);获取块,但它也会使用非感知块,例如

NSDictionary *dict = [array dictionaryByFilteringWithBlocksAndKeys:
                                    ^BOOL(id element) {return [element hasPrefix:@"a"];}, @"a", 
                                    ^(id element) {;}, @"c", 
                          nil];

没有抱怨。

有没有办法检查一个块在运行时是否与typedef具有相同的签名?

1 个答案:

答案 0 :(得分:4)

不,没有办法检查。这将需要编译器中的新语法。实际上,您希望“这些参数是可选的/可变参数,但必须遵循此类型模式”。

另请注意,将特定类型的参数列表视为va_list在技术上也不正确。对于大多数ABI而言,它主要是巧合,但不是全部。 (并不是说你这样做,但它经常出现在这些背景下)。

  

你能给我一个你特意打字的例子吗?   参数列表?

当然,请考虑:

id objc_msgSend(id,SEL,...);

这是一个var-args参数列表。现在,您可能认为可以这样做:

objc_msgSend(mutableArray, @selector(addObject:), anObject);

但是,从技术上讲,你做不到。根据C规范,varargs与特定类型的参数列表不兼容。因此,您需要进行类型转换:

void (*func)(id,SEL,id) = (void*)objc_msgSend;
func(mutableArray, @selector(addObject:), anObject);

也就是说,如果被调用的API是而不是也是varargs,那么必须根据具有完整参数类型信息的调用声明来编译调用站点...