Questo è esattamente il modo in cui la sintassi C funziona. La sintassi del blocco si basa su quella di function pointers, che si riduce all'idea di Dennis Ritchie secondo cui "la dichiarazione di una cosa dovrebbe apparire come l'uso di quella cosa".
Se si sceglie di usare il "complesso Block" è stato definito, e poi di chiamare anche la tornata di blocco nella stessa linea, sarebbe simile a questa:
complexBlock(void (^argBlock)(void){ /*...*/ })();
// ^Argument (a literal Block) to the main Block
// ^Invocation of the returned Block
Inoltre, l'analisi delle dichiarazioni C segue un cosiddetto "right-left rule". Il primo passo è "trova l'identificatore". Per la tua dichiarazione, è complexBlock
.
void (^(^complexBlock)(void (^)(void)))(void);
// | ! | Found identifier: "complexBlock is..."
Quindi, guarda a destra. Colpiamo una parentesi chiusa, quindi questa è la fine di una dichiarazione "unità".
void (^(^ )(void (^)(void)))(void);
// | ! Right parenthesis closes a part of the declaration
Torna all'inizio della parte corrente e leggi verso sinistra fino alla parentesi di apertura. Troviamo il segno di omissione che indica un tipo di blocco. Continua a leggere a sinistra e trova una parentesi aperta, chiudendo questa parte della dichiarazione.
void (^(^ (void (^)(void)))(void);
// |! | "...a Block..."
Successivamente, andare di nuovo a destra. Qui troviamo una parentesi aperta, che indica l'inizio di una lista di parametri. Salta l'elenco dei parametri poiché ti interessa il tipo di ritorno, ma viene analizzato come sarebbe una dichiarazione autonoma.
void (^ (void (^)(void)))(void);
// | ! | "...taking something or other and returning..."
Ora che abbiamo consumato la lista dei parametri:
void (^ )(void);
// | |
continuare lo spostamento a destra, e ci ha colpito una parentesi chiusa:
void (^ )(void);
// | !
Così, ancora una volta, indietro fino alla inizio della parte corrente e spostati a sinistra dove troviamo il punto di accesso al blocco.
void (^ (void);
// ! | "...a Block.."
Ecco la parte fondamentale per le tue domande su questa dichiarazione:
spostandosi a sinistra, ancora una volta troviamo una parentesi aperta, così abbiamo tornare lo spostamento a destra. Ecco perché la lista dei parametri di return Block va alla fine della dichiarazione.
void ( (void);
// ! | Left parenthesis closes part of declaration,
// **now move rightwards again**
Avendo attraversato tutto ciò, il resto dovrebbe essere evidente.
Per inciso, la pagina che ho collegato alla regola destra-sinistra ha alcune dimostrazioni come la mia, una delle quali riguarda i puntatori di funzione. Si può anche essere divertito da http://cdecl.org, che è un'implementazione online di un programma che analizza le dichiarazioni C e può aiutare a capire le varietà woolier.
"Perché la seconda sintassi non è ..." perché la sintassi del blocco deve adattarsi al resto del linguaggio C che ha 45 anni e tutti si aspettano che la sintassi sia così com'è. Swift ha una sintassi molto più bella del blocco, usalo se non ti piace la sintassi di Objective-C. –