2012-10-03 1 views
4

런타임에 주어진 블록의 인수 및 인수 유형을 확인하는 방법이 필요합니다. (현재 내가 작성하고있는 일부 객체 매핑 라이브러리에 이것을 필요로합니다. String을 매핑합니다. 형식화 된 값을 선택자로, 블록에 대해 동일하게 지정).NSBlock의 iOS NSMethodSignature (또는 encoding)

아래 예제에서 코드를 시도했지만 어떤 이유에서든 나를 위해 작동하지 않고 문자열 설명에 대해 returnin nil을 사용했습니다.

런타임에 블록 서명을 평가하는 방법을 알고 있습니까 (가급적이면 iPhone 앱 스토어 제출을 위해 아님)?

내가 사용하는 코드입니다 :

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