ios objective-c block introspection

iOS bloquea la introspección



objective-c block (2)

Me gustaría saber dos cosas:

1- ¿Es posible utilizando la introspección de object-c para saber el tipo de retorno de un bloque?

Por ejemplo: int (^CountBlock)(NSArray *array) Me gustaría saber si el tipo que devolverá es int .

La segunda pregunta es:

2- ¿Puedo mantener una referencia a un bloque genérico? Lo que quiero decir con esto es que básicamente puedo hacer algo como id myBlock y con esta respuesta la primera pregunta.

Lo que intenté

Este tipo de cosas no es posible:

id aBlock = ^{ NSString * aString = @"OMG"; return aString; }; aBlock();

Como el compilador ve que el id aBlock no es una función o un puntero de función.


1) Esta respuesta habla de cómo agarrar la firma de un bloque. Aquí está el código relevante:

static const char *BlockSig(id blockObj) { struct Block *block = (void *)blockObj; struct BlockDescriptor *descriptor = block->descriptor; int copyDisposeFlag = 1 << 25; int signatureFlag = 1 << 30; assert(block->flags & signatureFlag); int index = 0; if(block->flags & copyDisposeFlag) index += 2; return descriptor->rest[index]; }

Realmente no es lo ideal, ya que solo obtienes la cadena @encode de la firma, que se ve así: @"i16@?0@8" . Me encantaría ver si alguien tiene un mejor enfoque.

2) Definitivamente puedes lanzar bloques ay desde tipo id :

typedef void(^MyBlockType)(void); id aBlock = ^ { }; ((MyBlockType)aBlock)();

Por supuesto, si convierte al tipo de bloque incorrecto, terminará con un comportamiento indefinido.


Creo que el problema para el número 2 es que los bloques se nombran como parte de la definición de tipo, por ejemplo,

void (^blockName)(void) = ^{};

Una solución es definir un tipo de bloque genérico:

typedef void(^BlockType)(void); BlockType myBlock = ^{}; myBlock();

edición: señalada por @neilco, una forma mucho más sencilla de usar tipos de bloques de envío (que no devuelven nada y no aceptan argumentos):

dispatch_block_t myBlock = ^{}; myBlock();