1

GCD와 블록이 매우 유용하고 편리합니다. 그러나 내가 그것에 빠지면 뭔가 나쁜 일이 있음을 발견했습니다. 아래 코드를 살펴보십시오.중첩 된 블록을 피하는 방법

크레이지? 예. 나는이 문제에 빠져있다.

이렇게 중첩 된 블록을 피할 수있는 경험이 있습니까?

편집 :

고마워. 정확하게, 우리는 이것을 더 우아한 방법으로 가지고 있습니다. 예를 들면 :

  • 는 독립적 인 기능

로 블록을 사전에

  • 만들기 서브 블록을 선언하지만 제가 기대하는 것은 일반적인 솔루션입니다. 아마 다음과 같이 : (아래 의사 코드) 잘

    functionA.flat.success = [self functionB]; 
    functionB.flat.isntnil = [self functionC]; 
    functionB.flat.error = {}; 
    functionC.flat.isntnil = [self functionD]; 
    [flat call:functionA]; 
    
  • +0

    나는 당신이 어떤 종류의 대답을 기대하는지 잘 모르겠습니다. 블록을 피하려면 블록을 사용하는 메소드를 작성하지 마십시오. 그리고 당신이 그들을 파견하는 부분과 같이 그들을 필요로하더라도 정말로 나쁜 것은 없습니다. – NSAddict

    +0

    @NSAddict 예. 어쩌면 블록 지옥을 피할 수있는 비즈니스 로직 계층의 기능을 재 설계 할 수 있습니다. 하지만 여전히 일부 프레임 워크가 있는지 또는 구문 비설탕이 이러한 비동기 호출에 대해 편재 할 수 있는지 알고 싶습니다. – nickcheng

    +0

    심도있는 (광학) 중첩을 피하기 위해 각 블록의 안쪽 부분을 별도의 방법으로 이동할 수 있습니다. –

    답변

    5

    , 나는 중괄호를 닫는 클라우드 일치 귀찮게하지 않은,하지만 여기에 단순히 당신이 너무 블록 내에서 자유롭게 사용하고 절감 할 수있는 수익을 사용하여 시도이다 조금 중첩 : 또한

    [self functionA:^(BOOL success) { 
        if (!success) 
        return; 
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 
        [self functionB:^(NSError *error) { 
         if (!error) 
         return; 
    
         dispatch_async(dispatch_get_main_queue(), ^(void) { 
         [self functionC:^(id result) { 
          if (!result) 
          return; 
    
          [self functionD:^(BOOL success) { 
          if (!success) 
           return; 
    
          [self DoSomething]; 
          }]; 
         }]; 
         }); 
        }]; 
        }); 
    }]; 
    

    은 아무도 블록을 인라인를 작성하는 방법을 강제하지

    , 당신은 이전에 일반 변수로 선언하고 나중에 사용할 수 있습니다. 당신의 API는 사용자를 향한 관대하고 어떤 작업을 수행 할 수없는 경우에도 반복적으로 호출되는 것을 허용하는 경우 사실, 블록을 선언함으로써 당신은 그들을 재사용 할 수 있습니다 전에 : 나는 둥지 수준을 볼 때마다

    - (void)foo:(Bar*)bar 
    { 
        // Prepare the success handler. 
        void (^successBlock)(Bar*) = ^(Bar *bar) { 
    
         [[NSNotificationCenter defaultCenter] 
          postNotificationName:@"barUpdated" 
              object:bar]; 
        }; 
    
        if (!bar.didAlreadyFetchStuff) { 
         [self wellYouBetterFetchSomething:bar withSuccess:successBlock]; 
        } else { 
         // Oh, fake we already did the work. 
         successBlock(bar); 
        } 
    } 
    

    너무 높으면 클래스의 일반적인 메서드로 내부 블록을 넣고 블록 내부에서 호출하면됩니다. 효과는 동일하지만 훨씬 더 깨끗해 보입니다. 따라서 문서화되지 않은 중첩 된 블록의 혼란을 이해하기보다는 각 방법에 대해 appledoc 또는 기타 문서 도구를 사용할 수 있습니다.

    미친 짓을하는 경우에만 미치게됩니다.

    +0

    미리 블록을 선언하는 것이 코드를 단순화하는 가장 좋은 방법 중 하나입니다. – Sulthan

    관련 문제