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
非常感謝你,這工作。但什麼是「@?」?這是一個我應該忽略的隱藏論點嗎? – benjist
'@?'是塊的類型編碼。我猜測塊有一個隱藏的參數(塊本身可能),就像方法有隱藏的'self'和'_cmd'參數。 – 0xced