2

on the tutorial promgrammingWithObjectiveC.

The following code make me confuse:

Custom type definitions are particularly useful when dealing with blocks that return blocks or take other blocks as arguments. Consider the following example:

void (^(^complexBlock)(void (^)(void)))(void) = ^ (void (^aBlock)(void)) {
    ...
    return ^{
        ...
    };
};

The complexBlock variable refers to a block that takes another block as an argument (aBlock) and returns yet another block.

Rewriting the code to use a type definition makes this much more readable:

typedef void (^XYZSimpleBlock)(void);
XYZSimpleBlock (^betterBlock)(XYZSimpleBlock) = ^ (XYZSimpleBlock aBlock) {
    ...
    return ^{
        ...
    };
};

my understan the rewriting code : enter image description here but I can't understand the source code:

void (^(^complexBlock)(void (^)(void)))(void) = ^ (void (^aBlock)(void)) {
    ...
    return ^{
        ...
    };
}

in my understand, it should be:

(void (^) (void)) (^complexBlock) (void (^)(void) = ^ (void (^aBlock)(void)) {
    ...
    return ^{
        ...
    };
};
ruandao
  • 410
  • 4
  • 11
  • Of _course_ it's confusing. It's a C declaration! They are hard to read and always have been. :) – matt Feb 02 '14 at 19:24
  • `in my understand, it should be:` - no, why shouldn't it? Surely you know that blocks are declared similarly to functions. And that's not how the declaration of function return types work. Read a C book. –  Feb 02 '14 at 19:34

1 Answers1

5

Blocks are declared using syntax similar to that which is used to declare a pointer to a function, except that you use ^ instead of *.

So the function analogon would be a "pointer to a function that returns a function pointer", which is nicely explained here: https://stackoverflow.com/a/10759352/1187415.

If you translate the "building procedure" of that answer to your block then you get:

         complexBlock                          -- complexBlock
        ^complexBlock                          -- is a block
       (^complexBlock)(void (^)(void))         --   taking a block parameter
      ^(^complexBlock)(void (^)(void))         --   returning a block
     (^(^complexBlock)(void (^)(void)))(void)  --     taking no parameters
void (^(^complexBlock)(void (^)(void)))(void)  --     returning void

More generally, there is a technique called the "Clockwise/Spiral Rule" which you can use to "parse" a C declaration. The spiral rule works for blocks as well.

Or use cdecl C gibberish ↔ English, which in your case returns

declare complexBlock as block (block (void) returning void) returning
block (void) returning void
Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    Notice how Martin R develops his explanation of the declaration from the inside out, starting in the middle (the name) and then going outwards from there: one step left, one step right, one step left, one step right, one step left. That is how to read / write a C type declaration. And that's all a block type declaration is. – matt Feb 02 '14 at 19:27
  • @matt: It's called "spiral rule" (link added to answer). – Martin R Feb 02 '14 at 19:30
  • 1
    Great answer, Martin. Here's another nice reference to the spiral rule, applied to Objective-C block syntax http://nilsou.com/blog/2013/08/21/objective-c-blocks-syntax/ – Gabriele Petronella Feb 02 '14 at 21:41