Syntax to define a Block that takes a Block and returns a Block in Objective-C

五迷三道 提交于 2019-11-28 23:44:11
Josh Caswell

This is just how C syntax works. The Block syntax is based on that of function pointers, which boils down to Dennis Ritchie's idea that "the declaration of a thing should look like the use of that thing".

If you were to use the "complex Block" you defined, and then to also call the returned Block in the same line, it would look like this:

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

Further, the parsing of C declarations follows a so-called "right-left rule". The first step is "find the identifier". For your declaration, that's complexBlock.

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

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

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

Go back to the beginning of the current part, and read leftwards until an opening parenthesis. We find the caret indicating a Block type. Keep reading left, and find an opening parenthesis, closing off this part of the declaration.

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

Next, go right again. Here we find an opening parenthesis, indicating the start of a parameter list. Skip the parameter list since you're concerned with the return type, but it's parsed as a standalone declaration would be.

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

Now that we've consumed the parameter list:

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

continue moving right, and we hit a closing parenthesis:

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

So, again, back up to the beginning of the current part and move left where we find the Block caret.

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

Here's the key part for your question about this declaration:

Moving left, again we find an opening parenthesis, so we return to moving right. That's why the return Block's parameter list goes at the end of the declaration.

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

Having gone through all that, the rest should be self-evident.

Incidentally, the page I linked to about the right-left rule has a few demonstrations like mine, one of which involves function pointers. You may also be amused by http://cdecl.org, which is an online implementation of a program that parses C declarations and can help you understand the woolier varieties.

Obj-C block syntax is pretty hard to read, this can be simplified a bit with the use of 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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!