2013-08-21 1 views
1

다른 프로토콜을 자체적으로 상속하는 프로토콜을 정의하는보기 컨트롤러가 있습니다. 내 프로토콜을 구현하는 모든 개체에서 상속 된 프로토콜을 구현하기를 원합니다.objective C forwardingTargetForSelector가 항상 작동하지 않는 메시지 전달

내가 내부적으로 몇 가지를 구성하기 위해 상속 된 프로토콜의 메시지의 일부를 가로 채기 위해 내 수업을 설정하려는 결국

내가 쓸 수있는 내 클래스의 대리인에게 모든 메시지를 전달하고자 많은 보일러 플레이트 코드가 프로토콜과 인턴을 모두 스텁 (stub)하기 위해 위임자를 호출하지만 많은 시간을 쪼개는 것을 볼 수 있습니다. "수퍼"프로토콜이 변경되면이 클래스를 다시 복원해야합니다.

사용자 정의 UI 컨트롤에서 매우 두드러진 부분입니다. 예를 들어 테이블 또는 컬렉션 뷰와 같은 기존 구성 요소를 재사용 할 때는 데이터 소스가 모든 일반 프로토콜에 응답하기를 원하지만 일부 인스턴스에서는 인덱스에 따라보기를 구성하거나 특정 상태를 저장해야합니다.

내가 응답하지 않는 메시지를 전달하기 위해 forwardingTargetForSelector를 사용하여 시도했지만, 항상 전달되지 ... 여기

는 인위적인 코드 예제입니다

Class A: (the top most protocol) 

@ 

    protocol classAProtocol <NSObject> 

    -(void)method1; 
    -(void)method2; 
    -(void)method3; 

    @end 

    My Class 

    @protocol MyClassProtocol <classAProtocol> 

    -(void)method4; 
    @end 

    @interface MyClass 

    @property (nonatomic,weak> id <MyClassProtocol> delegate; 

    @end 

    @interface MyClass (privateInterface) 

    @property (nonatomic,strong) ClassA *classAObject; 
    @end 
    @implementation MyClass 

    -(init) 
    { 
     self = [super init]; 
     if (self) 
     { 
     _classAObject = [[ClassA alloc] init]; 
     _classAObject.delegate = self; // want to answer some of the delegate methods but not all 
     } 
    } 

-(void)method1 
{ 
    // do some internal configuration 
    // call my delegate with 
    [self.delegate method1]; 
} 
    -(id)forwardingTargetForSelector:(SEL)aSelector 
    { 
     if ([self respondsToSelector:aSelector]) 
     { 
      return self; 
     } 
     if ([self.delegate respondsToSelector:aSelector]) 
     { 
      return self.delegate; 
     } 
     return nil; 
    } 

    -(void)setDelegate:(id <MyClassProtocol>)delegate 
    { 
     self.delegate = delegate; // will forward some of the messages 
    } 
    @end 
+0

이 솔루션을 시도하고 다시 연락 할 것이다. –

답변

0

return self;부터 forwardingTargetForSelector:까지는 절대 안됩니다. 귀하의 수표는 결코 그렇지 않다는 것을 의미합니다. 그러나 self을 반환했다면 무한 루프가 발생할 것입니다.

forwardingTargetForSelector:이 호출되지 않도록 수퍼 클래스가 메소드를 구현하지 않아야합니다. 메소드가 실제로 호출되는지 확인하십시오.

forwardingTargetForSelector: 또한 컨트롤러에서 응답하지 않는 메서드가 호출 될 때만 호출됩니다. 예를 들어 [self ...];을 호출하지 않으면 [self.delegate ...];을 호출하므로 forwardingTargetForSelector:이 호출되지 않습니다.

+0

당신의 말에 분명하지 않습니다. 내 수업에서 말하면 self.someObject.delegate = self; 해당 대리자를 구현하지 않으면 메시지를 구현할 것으로 예상되는 내 대리자로 전달되지 않습니까? –

+0

코드를 작성하지 않으면 메서드가 다른 개체로 전달되지 않습니다. 'self'를 호출하고 그 메소드를 구현하지 않으면 (슈퍼 클래스가 그것을 구현하지 않는다면) 당신의'forwardingTargetForSelector'는 그것을 전달할 것입니다. – Wain

2

자기를 forwardingTargetForSelector:에서 되 돌리는 것은 셀프가 셀렉터에 응답 한 경우 절대로 호출되지 않으므로 의미가 없습니다.

는 이러한 세 가지 방법을 구현해야합니다

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    if ([self.delegate respondsToSelector:[anInvocation selector]]) 
     [anInvocation invokeWithTarget:self.delegate]; 
    else 
     [super forwardInvocation:anInvocation]; 
} 

- (BOOL)respondsToSelector:(SEL)aSelector 
{ 
    return [super respondsToSelector:aSelector] || [self.delegate respondsToSelector:aSelector]; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 
{ 
    NSMethodSignature *signature = [super methodSignatureForSelector:selector]; 
    if (!signature) { 
     signature = [self.delegate methodSignatureForSelector:selector]; 
    } 
    return signature; 
} 
+0

이러한 구현이 추가되었습니다. 세 번째 메소드 (methodSignatureForSelector)가 무엇인지 모릅니다. 선택기는 델리게이트에서 동일해야합니다? 또한 대리자가 [self.delegate methodSignatureForSelector : selector]를 호출하는 해당 메서드를 구현하지 않은 경우; 컴파일되지 않습니다. –

+0

NSInvocation을 구성 할 때 시스템에서 사용됩니다. 이렇게하면 내가 제공 한 코드의 모든 내용이 설명됩니다. https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html – atomkirk

관련 문제