iOS NSMethodSignature(或编码)的NSBlock

我需要一种方法来检查在运行时给定的块的参数和参数types的数量(我需要这个对于我正在写的一些对象映射库,我将string格式化的值映射到select器,要为块相同) 。

我尝试从下面的例子代码,但由于某种原因,它不适合我,并返回零string描述。

你知道在运行时评估块签名的方法吗(最好是iPhoneapp store的提交)?

这是我使用的代码:

struct BlockDescriptor { unsigned long reserved; unsigned long size; void *rest[1]; }; struct Block { void *isa; int flags; int reserved; void (*invoke)(struct __block_literal_1 *); struct BlockDescriptor *descriptor; }; enum { BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code BLOCK_IS_GLOBAL = (1 << 28), BLOCK_HAS_STRET = (1 << 29), // IFF BLOCK_HAS_SIGNATURE BLOCK_HAS_SIGNATURE = (1 << 30), }; static const char *BlockSig(id blockObj) { struct Block *block = (void *)blockObj; struct BlockDescriptor *descriptor = block->descriptor; assert(block->flags & BLOCK_HAS_SIGNATURE); int index = 0; if(block->flags & BLOCK_HAS_COPY_DISPOSE) index += 2; return descriptor->rest[index]; } -(NSString*)signatureForBlock:(id)block { NSString* sig = [NSString stringWithUTF8String:BlockSig(block)]; sig = [sig substringFromIndex:1]; // remove c NSArray* components = [sig componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789?"]]; sig = [components componentsJoinedByString:@""]; return sig; } 

然后做:

 NSString * (^block)(int, NSArray *) = ^NSString * (int i, NSArray * a){ return @"Oh, yeah!"; }; NSLog(@"signature %s", BlockSig(block)); // ==> this returns null 

来源: 检查Objective-C块types? https://github.com/mikeash/MABlockForwarding/blob/master/main.m

使用CTBlockDescription ,您可以获取所需的所有运行时信息作为NSMethodSignature对象。 用法很简单:

 NSString * (^block)(int, NSArray *) = ^NSString * (int i, NSArray * a){ return @"Oh, yeah!"; }; NSMethodSignature *signature = [[[CTBlockDescription alloc] initWithBlock:block] blockSignature]; NSLog(@"signature %@", [signature debugDescription]); 

这将输出以下签名:

 signature <NSMethodSignature: 0x6844900> number of arguments = 3 frame size = 12 is special struct return? NO return value: -------- -------- -------- -------- type encoding (@) '@' flags {isObject} modifiers {} frame {offset = 0, offset adjust = 0, size = 4, size adjust = 0} memory {offset = 0, size = 4} argument 0: -------- -------- -------- -------- type encoding (@) '@?' flags {isObject} modifiers {} frame {offset = 0, offset adjust = 0, size = 4, size adjust = 0} memory {offset = 0, size = 4} argument 1: -------- -------- -------- -------- type encoding (i) 'i' flags {isSigned} modifiers {} frame {offset = 4, offset adjust = 0, size = 4, size adjust = 0} memory {offset = 0, size = 4} argument 2: -------- -------- -------- -------- type encoding (@) '@' flags {isObject} modifiers {} frame {offset = 8, offset adjust = 0, size = 4, size adjust = 0} memory {offset = 0, size = 4}