2012-10-03 50 views
4

我需要一種方法來檢查在運行時給定塊的參數和參數類型的數量(我需要這個對於一些對象映射庫我正在寫,我映射字符串格式化值到選擇器,想要塊相同)。iOS NSMethodSignature(或編碼)NSBlock

我嘗試了下面的例子中的代碼,但由於某種原因,它不適用於我,並返回字符串描述爲零。

您是否知道在運行時評估塊簽名的方法(最好是iPhone應用商店提交的afe)?

這是我使用的代碼:

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:@"?"]]; 
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 

來源: Checking Objective-C block type? https://github.com/mikeash/MABlockForwarding/blob/master/main.m

回答

5

使用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} 
+0

非常感謝你,這工作。但什麼是「@?」?這是一個我應該忽略的隱藏論點嗎? – benjist

+0

'@?'是塊的類型編碼。我猜測塊有一個隱藏的參數(塊本身可能),就像方法有隱藏的'self'和'_cmd'參數。 – 0xced