2013-06-09 3 views
3

이 메서드를 사용하여 대리자에게 메서드를 디스패치합니다. 불행히도 NSMethodSignature가 nil 인 경우가 많습니다. 이는 선택기가 프로토콜에서 온다는 사실 때문입니다. 방법은 프로토콜 방법으로 당 NSMethodSignature 프로토콜

[편집]
의 서명을 받기 프로토콜

  • 에서 오는 경우

    1. 아크 스 : 나는 올바른 방법이다 궁금하네요 newacct 사용자 관측 나의 질문이 정확하지 않다, 서명이 nil이지만 프로토콜이 아니기 때문에 정상이 아니다. 그러나 잘못된 객체에 대해 메소드 서명을 요구하고 있기 때문에 그렇지 않다. Self이 경우에는 전달할 메서드를 구현하지 않으며이를 사용하고 구현하는 대리자입니다. 여기

      코드입니다 :

      - (BOOL) dispatchToDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err { 
      NSMethodSignature *methodSig = [[self class] instanceMethodSignatureForSelector:selector]; 
      NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 
      [invocation setTarget:self.delegate]; 
      BOOL result = NO; 
      if([self.delegate respondsToSelector: selector]) { 
           if(arg != NULL) { 
            [invocation setArgument:&arg atIndex:2];  
            [invocation setArgument:&err atIndex:3]; 
          }else { 
           [invocation setArgument:&err atIndex:2];  
      
          } 
          if ([NSThread isMainThread]) { 
           [invocation invoke];   
          } 
          else{ 
           [invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES]; 
          } 
          [invocation getReturnValue:&result]; 
      } 
      else 
          NSLog(@"Missed Method"); 
      return result; 
      } 
      


      [답변으로 업데이트] 나는 그것이 작동

      - (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector 
      { 
          NSMethodSignature *theMethodSignature = [super methodSignatureForSelector:inSelector]; 
          if (theMethodSignature == NULL) 
          { 
           struct objc_method_description theDescription = protocol_getMethodDescription(@protocol(GameCenterManagerDelegate),inSelector, NO, YES); 
           theMethodSignature = [NSMethodSignature signatureWithObjCTypes:theDescription.types]; 
          } 
          return(theMethodSignature); 
      } 
      

      그리고 애플의 메일 링리스트에서 발견하는 방법을 수정 한 하지만, 나는 bbum 제안을 따를 것이고, 코드는 훨씬 복잡 해져서 곧 깨질 것입니다.

      if ([delegate respondsToSelector:@selector(someMethod:thatDoesSomething:)]) { 
          dispatch_async(dispatch_get_main_queue(), ^{ 
           [delegate someMethod:foo thatDoesSomething:bar]; 
          } 
      } 
      

      런타임이 강하다과 마법 갈 유혹하지만 그냥 느린, 따라하기 어려운 지나치게 복잡한 코드 결과, 정말 많은 라인을 저장하지 않습니다

  • +0

    "NSMethodSignature가 대부분 없음을 알았습니다. 이것은 선택기가 프로토콜에서 온다는 사실 때문입니다." 이것은 의미가 없습니다. 'instanceMethodSignatureForSelector :'메소드 메쏘드를 얻는다. 메쏘드는 클래스가 메쏘드를 구현한다면 메쏘드의 서명을 반환한다. 프로토콜은 그 프로토콜과 아무 관련이 없습니다. – newacct

    +1

    요점은 메서드를 구현하는 클래스가 아니라 위임 패턴을 따르는 클래스이므로 프로토콜에서 다른 클래스 (대리자)로 프로토콜 메서드를 전달한다는 것입니다. 내가하고 싶었던 것은 NSInstance를 만들어 대의원에게 보냅니다. 아마 또 다른 방법은 change [[self class] instanceMethodSignatureForSelector : selector]; – Andrea

    답변

    3

    그냥 할 코드 리팩토링하는 것이 더 어렵습니다.

    이것은 분명히 반환 값을 설명하지 않습니다. 그렇다고해도 은 실제로 일종의 차단 호출을 피하려고합니다. 주 스레드에게 뭔가를하도록 지시 한 다음 완료되면 해당 큐에서 실행을위한 블록을 예약하도록합니다. 이렇게하면 교착 상태 위험이 줄어들고 전체 응용 프로그램 디자인이 훨씬 간단 해집니다.

    위의 코드는 주 스레드에서 호출 될 때 주 이벤트 루프를 통해 다음 번에 블록이 실행되도록합니다. 아마도 어쨌든 동시대 사건의 행동과 일관성이 있기를 원하는 것입니다.

    +0

    감사합니다. bbum에게 감사의 말을 전합니다. 내가 찾고있는 해결책을 찾았지만, 코드가 훨씬 복잡해지기 때문에 투어 조언을 따를 것입니다. 좀 더 간단하고 깨끗한 코드를 사용하는 더 쉬운 패턴을 발견 할 것입니다. – Andrea