2011-06-14 6 views
4

다음 코드는 컴파일과 잘 실행 (유의 sel_registerName("+")) :영숫자가 아닌 문자를 선택자로 사용할 수 있습니까?

"윽"이외의
#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 
#import <objc/message.h> 

@interface Integer : NSObject 
{ 
    NSInteger intValue; 
} 

@property (assign) NSInteger intValue; 

@end 

@implementation Integer 

@synthesize intValue; 

- (id) plus:(Integer*)anInteger 
{ 
    Integer* outInt = [Integer new]; 
    [outInt setIntValue: intValue + [anInteger intValue]]; 
    return outInt; 
} 

@end 


int main (int argc, char const *argv[]) 
{ 
    id pool = [[NSAutoreleasePool alloc] init]; 

    SEL plusSel = sel_registerName("+"); 
    Method m = class_getInstanceMethod([Integer class], @selector(plus:)); 
    class_addMethod([Integer class], plusSel, method_getImplementation(m), method_getTypeEncoding(m)); 

    Integer* i4 = [Integer new]; 
    Integer* i20 = [Integer new]; 
    [i4 setIntValue: 4]; 
    [i20 setIntValue: 20]; 

    Integer* res = objc_msgSend(i4, plusSel, i20); 

    NSLog(@"%d + %d = %d", [i4 intValue], [i20 intValue], [res intValue]); 
    // >> 4 + 20 = 24 

    [pool drain]; 
    return 0; 
} 

,이 일에 대해 신중해야하는 이유가?

+0

재미는 모든 종류의 재미에 사용할 수 있습니다. 이상적인 것은 아닙니다. –

답변

1

ObjC 런타임에 대한 API는 변경되지 않지만 sel_registerName ("+") 호출의 유효성은 변경 될 수 있습니다. 나는 ObjC 런타임에서 많이 놀랐으며 많은 업데이트 후에도 문제가 발생하지 않았다. 즉, 나는 계속해서 영원히 계속할 수있는 수백만 달러짜리 비즈니스를 기반으로하지 않을 것이라고 말했다.

0

현재 Objective-C 런타임 라이브러리는 등록하려는 문자열의 내용을 검사하지 않으므로 개발 팀이 해당 동작을 변경하지는 않습니다. 비어 있지 않은 C 문자열 인 경우 항상 objc_msgSend을 사용하여 해당 선택기에 대한 메시지를 보내고 [i4 +:i20] (컴파일 오류의 원인이 될 수 있음)을 시도하지 않으면 아무 이유도 없습니다. 두려워.

등록 된 Objective-C 선택자는 실제로 런타임 시스템에 의해 내부적으로 저장된 C 문자열입니다. 런타임 시스템은 C 문자열에 대한 포인터 테이블 (소위 SEL 세트)을 유지합니다. sel_registerName을 호출하면 ObjC 런타임 시스템이 문자열 및 SEL 집합에 저장된 각 C 문자열에 대해 strcmp을 호출합니다. SEL 세트의 C 문자열 중 하나라도 등록하려는 것과 같으면이 세트의 해당 C 문자열의 주소를 반환합니다. 그렇지 않으면 시스템은 문자열 (strdup)을 복제하고 결과 포인터를 SEL 세트에 저장 한 다음이를 반환합니다. 이 새 포인터는 새로운 고유 선택기가됩니다.

관련 문제