Интроспекция блоков iOS

Я хотел бы знать две вещи:

1 - Возможно ли, используя objective-c интроспекцию знать тип возврата блока.

Например: int (^CountBlock)(NSArray *array) Я хотел бы знать, какой тип он будет возвращать: int.

Второй вопрос:

2 - Могу ли я использовать ссылку на общий блок? Я имею в виду с этим, в основном я могу сделать что-то вроде id myBlock и с этим ответом первый вопрос.

Что я пробовал

Этот вид материала невозможен:

id aBlock = ^{

    NSString * aString = @"OMG";

    return aString;
};

aBlock();

Как компилятор видит, что id aBlock не является функцией или указателем функции.

Ответы

Ответ 1

1) Этот ответ рассказывает о том, как захватить подпись блока. Вот соответствующий код:

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];
}

Это действительно не идеально, поскольку вы просто получаете строку @encode подписи, которая выглядит так: @"[email protected][email protected]". Мне бы хотелось узнать, есть ли у кого-то лучший подход.

2) Вы можете определенно лить блоки в и из типа id:

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

Конечно, если вы примените неверный тип блока, вы получите поведение undefined.

Ответ 2

Я думаю, что проблема для числа 2 заключается в том, что блоки называются частью определения типа, например.

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

Обходным путем является определение типа общего типа:

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

edit: указана @neilco, гораздо более простой способ использования типов блоков отправки (которые ничего не возвращают и не принимают никаких аргументов):

dispatch_block_t myBlock = ^{};
myBlock();