用于定义块的块的语法,该块采用块并在Objective-C中返回块

时间:2014-11-27 03:22:56

标签: objective-c syntax objective-c-blocks declaration

我在Apple的文档Working with Blocks中找到了定义块的语法,该块返回乘以两个值的结果:

double (^multiplyTwoValues)(double, double);

不同于定义一个块,该块将另一个块作为参数并返回另一个块:

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

为什么第二种语法不是void (^)(void)(^complexBlock)(void (^)(void))

2 个答案:

答案 0 :(得分:18)

这就是C语法的工作原理。 Block语法基于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..."

然后,向右看。我们点了一个右括号,所以这是声明“单位”的结尾。

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

返回当前部分的开头,向左阅读直到左括号。我们发现插入符号表示块类型。继续阅读,找到一个左括号,关闭声明的这一部分。

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

接下来,再往右走。这里我们找到一个左括号,表示参数列表的开始。由于您关注的是返回类型,因此跳过参数列表,但它被解析为独立的声明。

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

现在我们已经使用了参数列表:

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

继续向右移动,我们点了一个右括号:

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

所以,再次回到当前部分的开头,向左移动,找到Block插入符号。

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

以下是关于此声明的问题的关键部分:

向左移动,我们再次找到一个左括号,所以我们返回右移。这就是返回Block的参数列表在声明结束时的原因。

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

经历了这一切,其余的应该是不言而喻的。

顺便提一下,我链接到左右规则的页面有一些类似我的演示,其中一个涉及函数指针。您也可能被http://cdecl.org逗乐,这是一个解析C声明的程序的在线实现,可以帮助您理解较为粗糙的变种。

答案 1 :(得分: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);