La mejor práctica para declarar los bloques Objective-C como variable

Tengo una pregunta sobre la mejor práctica para declarar un bloque como una variable .

Inicialmente escribí mi variable de bloque así:

id actionHandler = ^(UIAlertAction * action) { // Handling code }; 

Para luego usarlo así:

 UIAlertAction *action = [UIAlertAction actionWithTitle:@"Title" style:UIAlertActionStyleDefault handler:actionHandler]; 

Pero cuando me topé con la guía Trabajando con Bloques de Apple , vi que podía reescribirlo así:

 void (^actionHandler)(UIAlertAction * action) = ^(UIAlertAction * action) { // Handling code }; 

¿Es esta la forma "correcta" de declararla? Eso, en mi opinión, no es tan legible, pero no tengo mucha experiencia con Objective-C. Entonces, ¿cuál es la mejor práctica para declarar un bloque como una variable?


Edit: Bien, gracias a todos por la aclaración! Definir un typedef como se muestra por amin-negm-awad y otros parece ser un buen enfoque alternativo también.

Aquí no hay una respuesta para todos: cuando declara su variable de bloque como id , ya no tiene información de time de compilation asociada con su bloque, por lo que llamarlo manualmente se vuelve problemático:

 id myHandler = ^(NSString *str) { NSLog(@"%@", str); }; // Error: Called object type id is not a function or function pointer myHandler(@"Hello"); 

si desea hacer una llamada directa al bloque desde su código, debe devolverlo a un bloque.

Por otro lado, si declara una variable de bloque solo para poder pasarla a una function que toma un bloque como un parámetro, usar id proporciona un enfoque más legible.

Además del problema mencionado por dasblinkenlicht, quiero hacer una pregunta retórica:

Probablemente sepa que puede sustituir este código …:

 NSString *string = @"All about types"; 

… con este código:

 id string = @"All about types"; 

¿Harías? Estoy seguro de que no lo haces.

Entonces, ¿por qué se debe cambiar la versión "typed" de la var en una versión id ? La única razón es que la syntax de los types de bloques no es fácil de leer (y no es fácil de escribir). Siempre defino un tipo concreto para deshacerse de la syntax sencilla:

 typedef void (^ActionHandlerType)(UIAlertAction * action); 

Y entonces:

 ActionHandlerType actionHandler = ^(UIAlertAction * action) { // Handling code }; 

Para dejarlo en claro: id es genial usar la naturaleza dinámica del paso del post de Objective-C. Pero la ejecución de bloque no está vinculada tarde. Ni los parameters del bloque pueden cambiar su número o tipo, por lo que no hay nada que obligar de forma dinámica. Es una llamada simple con numbers fijos de arguments, fija mecanografiada. Por lo tanto, el uso de id es posible como un efecto secundario de la naturaleza del object del bloque. Pero no es un uso, que está destinado.

BTW: si usa un tipo concreto en una list de parameters, Xcode puede autocomplete la syntax del argumento. Con id esto no es posible. Obviamente.

Si usa id en este context, el comstackdor no comprobará que el tipo del bloque que declara coincide con el tipo de bloque que espera el método. Si accidentalmente consigues que el bloque sea incorrecto desagradable, difícil de depurar, es probable que suceda cuando el método intenta usar el bloque …

Así que si nunca cometes errores, ve con id , pero si, como yo, proporcionas el tipo correcto para que el comstackdor pueda ayudarte cuando lo hagas.

Para que sea más fácil y, por consiguiente, less propenso a errores, use un typedef, por ejemplo:

 typedef void (^AlertActionHandler)(UIAlertAction * action); ... AlertActionHandler actionHandler = ^(UIAlertAction * action) { ...