我是Objective C和iOS开发的初学者,但是13年的.NET资深人士。我很难在心理上绘制以下声明,该声明来自Programming with Objective C指南:
void (^(^a)(void (^) (void))) (void) = ...
它用作为什么应该使用typedef
来定义块的示例,但我想了解我正在考虑的内容,以便首先更好地了解块定义语法。
以下是我到目前为止的图表:
我遇到问题的地方是我理解基本语法:
[return_val] (^[block_name]) ([block_args]) = ...
如果是这种情况,那么我所拥有的是一个返回void并且没有参数的块,但是名为(^a) (void (^) void)
。这意味着我的块的名称,而不是一个直的字符串,本身就是一个块。
显然我在这里遗漏了一些东西。有人可以对此有所了解吗?根据该网站,它简化了这一点:
typedef void (^SimpleBlock) (void);
SimpleBlock (^complexBlock) (SimpleBlock) = ...
我只是错过了。
编辑:第三个空格应该在括号中。我修好了。它在图像中是错误的,但我不想为此重做整个图像。 :)如果结果是问题的根源,我会在这里修复它。
答案 0 :(得分:10)
在您的示例中,您错过了第三个 void
void (^(^a)(void (^)(void)))(void)
现在让我们分解吧。从函数返回块的基本语法是:
void (^f())(void) {
return ^{};
}
在此示例中,返回的块不带参数,并返回void 。
现在让我们建立你的榜样。
void (^myBlock)(void); // Block returning void, taking no args
void (^myBlock)(void (^)(void)); // Block returning void, taking block as arg
int (^myBlock)(void (^)(void)); // Block returning int, taking block as arg
void (^ (^myBlock)(void (^)(void)) )(void); // Block returning block, taking block as arg
我已将每一行的中心部分对齐,以便于阅读。所以困难的部分似乎正在回归一个街区。在最后一行中,我们使用前面描述的语法从函数返回一个块。
显然typedefs
使阅读更容易。
编辑:
考虑这个示例,在第一行中,我使用直观返回语法替换int
block
:
void (^ )(void) (^myBlock)(void (^)(void)); // Syntax we 'intuitively would use'
void (^ (^myBlock)(void (^)(void)) )(void); // Official syntax
我不是百分之百确定我要说的是什么,但我怀疑这种奇怪语法的原因是编译器中的解析器不会混淆。第一个“直观”语法会让编译器认为我们有一个块不带参数返回void ,剩下的字符将被视为语法错误。
在我看来,语法是你不要过多质疑的东西(你当然可以批评它),因为它是语言设计的一部分,我们必须遵循规则(由一些希望聪明的工程师设定) )为我们的代码编译。
答案 1 :(得分:0)
void (^(^a)(void (^) (void))) (void)
将这些语法分成几部分:
a
是一个变量。^a
。(^a)(void (^) (void)
是一个名为a
的块,并以块(void (^) (void)
作为参数。^(^a)(void (^) (void))
。 (并暗示返回值因此是一个块指针)(^(^a)(void (^) (void))) (void)
。void (^(^a)(void (^) (void))) (void)
所以我们说(^a) (void (^) void)
不是Meaning the name of my block, rather than being a straight string, is itself a block.
。块文字不一定是
[return_val] (^[block_name]) ([block_args])
编译器会将插入符号作为块后面的代码。