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 ^{
        ...
    };
};
2
  • Of course it's confusing. It's a C declaration! They are hard to read and always have been. :) Commented Feb 2, 2014 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. Commented Feb 2, 2014 at 19:34

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

3 Comments

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: It's called "spiral rule" (link added to answer).
Great answer, Martin. Here's another nice reference to the spiral rule, applied to Objective-C block syntax nilsou.com/blog/2013/08/21/objective-c-blocks-syntax

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.