2014-11-27 4 views
8
내가 구문이 두 값을 곱한 결과를 반환 블록 정의하는 것이 애플의 문서 Working with Blocks에서 찾을

의 블록을 블록을 받아 반환하는 블록 정의 :구문 오브젝티브 C

double (^multiplyTwoValues)(double, double); 

인을

void (^(^complexBlock)(void (^)(void)))(void); 

왜 번째 구문 void (^)(void)(^complexBlock)(void (^)(void))이 아니다 : 인수로 다른 블록을 취하고 또 다른 블록을 반환하는 정의 블록 상이한?

+0

"왜 두 번째 구문이 그렇지 않은 ... ..."블록 구문이 45 년 된 C 언어의 나머지 부분에 맞아야하고 모든 사람들이 구문을 기대하기 때문에 "두 번째 구문이 그렇지 않은 이유는 ..."입니다. Swift는 Objective-C의 구문이 마음에 들지 않는다면 훨씬 더 멋진 블록 구문을 사용합니다. –

답변

14

이것은 C 구문이 작동하는 방법입니다. 블록 구문은 function pointers의 구문을 기반으로하며 데니스 리치 (Dennis Ritchie)의 생각에 따르면 "그 것의 선언은 그 것을 사용하는 것처럼 보일 것"이라고합니다. 당신은 "복잡한 블록"사용자가 정의한 다음 같은 줄에 반환 된 블록 전화를 사용한다면

, 그 결과는 다음과 같습니다

complexBlock(void (^argBlock)(void){ /*...*/ })(); 
//   ^Argument (a literal Block) to the main Block 
//           ^Invocation of the returned Block 

을 또한, C 선언의 구문 분석 소위 "right-left rule"을 따릅니다. 첫 번째 단계는 "식별자 찾기"입니다. 귀하의 신고에 대해서는 complexBlock입니다.

void (^(^complexBlock)(void (^)(void)))(void); 
//  |  ! | Found identifier: "complexBlock is..." 

그런 다음 오른쪽을보십시오. 우리는 닫는 괄호를 쳤다. 그래서 이것은 "unit"선언의 끝이다.

void (^(^   )(void (^)(void)))(void); 
//  |   ! Right parenthesis closes a part of the declaration 

현재 파트의 시작 부분으로 돌아가서 여는 괄호까지 왼쪽으로 읽습니다. 블록 타입을 나타내는 캐럿을 찾습니다. 왼쪽을 계속 읽은 다음 여는 괄호를 찾아 선언의이 부분을 닫습니다.

void (^(^    (void (^)(void)))(void); 
//  |!   | "...a Block..." 

다음으로 다시 이동하십시오. 여기서 우리는 매개 변수 목록의 시작을 나타내는 여는 괄호를 찾습니다. 리턴 타입에 관심이 있기 때문에 매개 변수 목록을 건너 뛰지 만, 독립형 선언이 될 때 구문 분석됩니다.

void (^        )(void); 
//  |       | 

오른쪽으로 이동을 계속, 우리는 닫는 괄호 명중 : 다시까지, 다시, 그래서

void (^        )(void); 
//  |        ! 

를 우리는 매개 변수 목록을 소비했습니다 이제

void (^    (void (^)(void)))(void); 
//  |    !    | "...taking something or other and returning..." 

현재 부분의 시작 부분과 왼쪽으로 이동하여 블록 캐럿을 찾습니다. 다시 우리가 여는 괄호를 찾을

가 왼쪽으로 이동 그래서 우리는 바로 이동로 돌아 :

void (^        (void); 
// !        | "...a Block.." 

다음은이 선언에 대한 질문의 핵심 부분입니다. 그렇기 때문에 반환 블록의 매개 변수 목록이 선언의 마지막에 오는 이유입니다.

void (        (void); 
// !        | Left parenthesis closes part of declaration, 
//          **now move rightwards again** 

나머지는 모두 분명합니다.

덧붙여 말하자면, 우상 룰에 링크 된 페이지에는 광산과 같은 몇 가지 데모가 있습니다. 그 중 하나는 함수 포인터를 포함합니다. http://cdecl.org은 C 선언을 구문 분석하고 털이 많은 종류를 이해하는 데 도움이되는 프로그램의 온라인 구현입니다.

+0

매우 자세한 설명입니다. Objective C 블록에 대한 많은 의문점을 해결했습니다. – Kampai

+1

좋은 대답입니다. C 구문은 읽기가 어렵습니다. –

1

Obj-C 블록 구문은 읽기가 어렵지만 typedef를 사용하면 약간 복잡해질 수 있습니다.

//setup 
typedef void (^ReturnedBlock)(void); 
ReturnedBlock retBlock = ^void(void){}; 

typedef void (^ParamBlock)(void); 
ParamBlock paramBlock = ^void(void){}; 

//the thing you want to do 
ReturnedBlock (^someBlock)(ParamBlock) = ^ReturnedBlock(ParamBlock param){ 

    return retBlock; 
}; 

//perform the block 
ReturnedBlock r = someBlock(paramBlock); 
+0

ReturnedBlock에 void가 반환되고 ParamBlock에 void 매개 변수가 있습니다. –

+0

나는 당신이 원하는대로 typedef를 사용자 정의 할 수 있다는 것을 알고있다. 주요 아이디어는 typedef를 사용하여 블록을 더 읽기 쉽고 이해하기 쉽도록 만든 다음 구문이 중요하지 않게 만드는 것입니다. – Nick