Интроспекция блоков 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();