我在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_list
从TestBlock block = va_arg(args, TestBlock);
获取块,但它也会使用非感知块,例如
NSDictionary *dict = [array dictionaryByFilteringWithBlocksAndKeys:
^BOOL(id element) {return [element hasPrefix:@"a"];}, @"a",
^(id element) {;}, @"c",
nil];
没有抱怨。
有没有办法检查一个块在运行时是否与typedef具有相同的签名?
答案 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,那么必须根据具有完整参数类型信息的调用声明来编译调用站点...