【问题标题】:iOS NSMethodSignature (or encoding) of NSBlockNSBlock 的 iOS NSMethodSignature(或编码)
【发布时间】:2012-09-24 19:11:36
【问题描述】:

我需要一种方法来在运行时检查给定块的参数数量和参数类型(我需要这个用于我当前正在编写的一些对象映射库,我正在将字符串格式的值映射到选择器,想要相同块)。

我尝试了以下示例中的代码,但由于某种原因,它对我不起作用,并且返回 nil 作为字符串描述。

你知道在运行时评估区块签名的方法吗(最好是对 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:@"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

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

【问题讨论】:

    标签: ios objective-c-blocks encode


    【解决方案1】:

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

    【讨论】:

    • 非常感谢,这行得通。但什么是“@?”?这是一个我应该忽略的隐藏论点吗?
    • @? 是块的类型编码。我猜块有一个隐藏参数(可能是块本身),就像方法有隐藏的self_cmd 参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 2012-01-15
    • 1970-01-01
    相关资源
    最近更新 更多