I created a veriadic Category method on NSArray to filter it into a dictionary with given blocks and keys
typedef BOOL (^TestBlock)(id element);
- (NSDictionary *)dictionaryByFilteringWithBlocksAndKeys:(TestBlock)firstBlock, id firstKey,... NS_REQUIRES_NIL_TERMINATION;
Usage:
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];
It works quite good, but I wonder, how I can check, if a given block (other then the first) has the typedef’ed signature.
I get the blocks from the va_list with TestBlock block = va_arg(args, TestBlock);, but it also eats non-sense blocks like
NSDictionary *dict = [array dictionaryByFilteringWithBlocksAndKeys:
^BOOL(id element) {return [element hasPrefix:@"a"];}, @"a",
^(id element) {;}, @"c",
nil];
without complaining.
Is there a way to check, if a block has the same signature as a typedef at runtime?
No, there is no way to check. This would require new syntax in the compiler. Effectively, you want “these arguments are optional/variadic, but must follow this type pattern”.
Also note that treating a specifically typed argument list as a
va_listis not technically correct, either. It will mostly work by coincidence on most ABIs, but not all. (Not that you are doing that, but it often comes up in these contexts).Sure, consider:
That is a var-args argument list. Now, you might think you can do this:
But, technically, you can’t. varargs are not compatible with specifically typed argument lists, by the C spec. Thus, you need to typecast:
That is, if the called API is not also varargs, then the call site must be compiled against a declaration of the call that has full argument type info…