2010-04-26 5 views
27

SEL 개체를 모두 가지고있을 때 몇 가지 인수로 선택기를 호출하는 쉬운 방법이있는 것처럼 보입니다. 올바른 구문을 찾을 수없는 것 같습니다.SEL performSelector 및 arguments

인수로 유형 id 중 하나 개 또는 두 개의 객체를 취할 방법에 대한
-(MyClass*) init: (SEL)sel owner:(NSObject*) parent 
{ 
    int i =10; 
    [parent performSelector:sel:i ]; 
} 

답변

74

NSObject 문서를 살펴보십시오.

[parent performSelector:sel withObject:[NSNumber numberWithInt:i]]; 

(이 방법은 실제로 NSObject protocol 문서에 나와 있습니다) :이 경우. -[NSObject performSelector:withObject:] 객체 인수를 필요로하기 때문에, 당신은 NSNumber을 언 박싱하는

-(void)myMethodForNumber:(NSNumber*)number { 
    [self myMethod:[number intValue]]; 
} 

처럼 부모의 클래스 래퍼를 작성해야합니다.

실제로 비 개체 인수를 사용하는 메서드를 호출하려는 경우 (예를 들어, 호출 수신자를 제어하지 않고 범주를 추가하지 않으려는 경우) NSInvocation :

을 사용할 수 있습니다
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]]; 
[inv setSelector:sel]; 
[inv setTarget:parent]; 
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation 
[inv invoke]; 

메서드가 init 인 것처럼 보이지만 Objective-C의 올바른 초기화 프로그램 패턴을 따르지 않습니다. 수퍼 클래스 이니셜 라이저를 호출해야하며 해당 호출에서 nil 결과를 테스트해야하며 이니셜 라이저 메서드에서 self를 반환해야합니다. (가 init 메소드의 경우) 다음과 같을 것이다

-(id)myInitMethod { 
    self = [super init]; 
    if(self != nil) { 
     //perform initialization of self 
    } 

    return self; 
} 

귀하의 방법 : 모든 경우에, 당신의 목표 - C 초기화 방법이 같아야합니다

-(id) init: (SEL)sel owner:(NSObject*) parent 
{ 
    self = [super init]; 
    if(self != nil) { 
     int i = 10; 
     NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]]; 
     [inv setSelector:sel]; 
     [inv setTarget:parent]; 
     [inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation 
     [inv invoke]; 
    } 

    return self; 
} 

이 문체 더 오브젝티브 C가 될, 나는 이니셜 라이저 -(id)initWithSelector:owner:의 이름을 바꿀 것입니다.

+0

감사합니다. NSInvocation을 사용해야 할 수도 있지만 확실하지는 않다고 생각했습니다. 좋은 대답. – madmik3

+0

참고로, 호출 수신자를 제어 할 수 없더라도 해당 클래스의 카테고리를 사용하여 래퍼 메소드를 작성하여 객체를 기본 유형으로 unbox 할 수 있습니다. –

+0

좋은 지적, 에드. –

1

, 당신은 사용할 수 있습니다

[parent performSelector:sel withObject:argument1]; 

또는 다른 인수 유형과 방법에 대한

[parent performSelector:sel withObject:argument1 withObject:argument2]; 

는, NSInvocation를 만들 임의의 메소드 호출을 캡슐화 할 수 있습니다.

+0

정확한 방법 서명을 정량화하십시오. NSSelectorFromFromString (methodWithArg1 : arg2 :) – stephen

2

performSelector:withObject: 까다로운 부분은 int을 NSObject로 변환하는 것입니다. performSelector에는 int 매개 변수를 사용하는 메시지를 사용할 수 없으며 대신 id을 사용해야합니다. NSObject Protocol Reference에서

:

aSelector 유형 아이디의 인수를 취하는 방법을 식별해야합니다. 다른 인수 유형 및 반환 값을 갖는 메소드의 경우 NSInvocation을 사용하십시오.

그 변경이되면, 당신은 할 수 있습니다 :

id arg = [NSNumber numberWithInt:10];  
[parent performSelector:sel withObject:arg]; 
1

당신은 사용할 수 있습니다

- (id)performSelector:(SEL)aSelector withObject:(id)anObject 
- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject 

을 또는 당신이 필요로하는 경우 더 복잡한 방법의 사용을 NSInvocation 클래스를 사용하는

11

Barry Wark가 말한 바에 의하면 .. 게으른 프로그래머를위한 토론을 수정했습니다.

-(void)myMethodWith:(int)number andBOOL:(BOOL) someBool andStr:(NSString *)str{ 
    NSLog(@"%d %d %@",number,someBool,str); 
} 

-(void) testMethod{ 
    SEL sel = @selector(myMethodWith:andBOOL:andStr:); 
    int i = 10; 
    BOOL bol = YES; 
    NSString *str = @"hey baby !"; 
    NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:sel]]; 
    [inv setSelector:sel]; 
    [inv setTarget:self]; 
    [inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation 
    [inv setArgument:&bol atIndex:3]; 
    [inv setArgument:&str atIndex:4]; 
    [inv invoke]; 
} 
관련 문제