Necesita ayuda con respecto a la comprensión de typedefs y bloques

typedef void (^RequestProductsCompletionHandler)(BOOL success, NSArray * products); 

Tengo dificultades para entender qué está haciendo esta línea de código en el file .h.

Por favor explique en detalle

  1. typedef
  2. vacío (sé qué hace el vacío, pero ¿cuál es el propósito aquí?).
  3. (^ RequestProductsCompletionHandler) (éxito BOOL, productos NSArray *);
  4. Como llamarlo

Esta es la definición del tipo de bloque objective-c con el nombre RequestProductsCompletionHandler que toma 2 parameters (BOOL y NSArray) y no tiene valor de retorno. Puede llamarlo del mismo modo que llamaría a la function c, por ejemplo:

 RequestProductsCompletionHandler handler = ^(BOOL success, NSArray * products){ if (success){ // Process results } else{ // Handle error } } ... handler(YES, array); 

Vladimir lo describió bien. Define un tipo de variable que representará un bloque que pasará dos parameters, un success boolean y una matriz de products , pero el bloque en sí mismo vuelve void . Si bien no es necesario utilizar el typedef , hace que la statement del método sea un poco más elegante (y evita tener que participar en la complicada syntax de las variables de bloque).

Para darle un ejemplo práctico, se podría inferir del nombre del tipo de bloque y sus parameters que esto define un bloque de finalización (por ejemplo, un bloque de código que se debe realizar cuando se completa una operación asíncrona, como una request de networking lenta). Consulte Uso de un bloque como argumento de método .

Por ejemplo, imagine que tenía alguna class de InventoryManager desde la que podría solicitar información del producto, con un método con una interfaz definida como tal, usando su typedef :

 - (void)requestProductsWithName:(NSString *)name completion:(RequestProductsCompletionHandler)completion; 

Y puede usar el método así:

 [inventoryManager requestProductsWithName:name completion:^(BOOL success, NSArray * products) { // when the request completes asynchronously (likely taking a bit of time), this is // how we want to handle the response when it eventually comes in. for (Product *product in products) { NSLog(@"name = %@; qty = %@", product.name, product.quantity); } }]; // but this method carries on here while requestProductsWithName runs asynchronously 

Y, si requestProductsWithName la implementación de requestProductsWithName , podría concebir algo así como:

 - (void)requestProductsWithName:(NSString *)name completion:(RequestProductsCompletionHandler)completion { // initiate some asynchronous request, eg dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // now do some time consuming network request to get the products here // when all done, we'll dispatch this back to the caller dispatch_async(dispatch_get_main_queue(), { if (products) completion(YES, products); // success = YES, and return the array of products else completion(NO, nil); // success = NO, but no products to pass back }); }); } 

Claramente, es improbable que esto sea precisamente lo que está haciendo su bloque de event handling finalización particular, pero es de esperar que ilustre el concepto.

Mike Walker creó un bonito sitio de una página que muestra todas las posibilidades de declarar un bloque en Objective-C. Esto puede ser útil para comprender su problema también:

http://fuckingblocksyntax.com

Para citar su sitio, así es como puede definir bloques:

Como variable local:

 returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...}; 

Como propiedad:

 @property (nonatomic, copy) returnType (^blockName)(parameterTypes); 

Como parámetro de método:

 - (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName {...} 

Como argumento a una llamada de método:

 [someObject someMethodThatTakesABlock: ^returnType (parameters) {...}]; 

Como typedef:

 typedef returnType (^TypeName)(parameterTypes); TypeName blockName = ^(parameters) {...}