Syntax for defining a block that accepts a block and returns a block in Objective-C

I found in Apple's document Working with Blocks , so that the syntax defines a block that returns the result of multiplying two values:

double (^multiplyTwoValues)(double, double); 

differs from the definition of a block, which takes another block as an argument and returns another block:

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

Why is the second syntax not void (^)(void)(^complexBlock)(void (^)(void)) ?

+8
syntax objective-c declaration objective-c-blocks
source share
2 answers

This is how the C syntax works. Block's syntax is based on the function pointer syntax, which boils down to Dennis Ritchie’s idea that "the declaration of a thing should look like using this thing."

If you must use the "complex block" that you defined, and then also call the returned block on the same line, it will look like this:

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

Next, the parsing of C declarations follows the so-called right-left rule . The first step is to find the identifier. For your ad, this is complexBlock .

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

Then, look to the right. We press the closing parenthesis, so this is the end of the unit declaration.

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

Go back to the beginning of the current part and read left to open the parenthesis. We find a caret indicating the type of block. Continue reading to the left and find the open parenthesis, closing this part of the declaration.

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

Then go right again. Here we find the initial bracket indicating the beginning of the parameter list. Skip the parameter list since you are interested in the return type, but it is parsed as a standalone declaration.

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

Now that we have used the parameter list:

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

continue to the right and we will press the closing bracket:

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

So, go back to the beginning of the current part and move to the left, where we find the carriage block.

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

Here is the key part of your question about this announcement:

Moving to the left, again we find the open parenthesis, so we return to the correct movement. This is why the list of return list options goes at the end of the declaration.

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

After going through all this, the rest should be taken for granted.

By the way, on the page that I referenced in the rule on the right, there are several demos like mine, one of which includes pointers to functions. You may also be surprised at http://cdecl.org , which is an online implementation of a program that analyzes C declarations and can help you understand milder varieties.

+14
source share

The syntax of the Obj-C block is pretty hard to read; it can be simplified a bit with typedefs.

 //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); 
+1
source share

All Articles