Выполнение блоков из NSArray?
Я просто думал, так как вы можете рассматривать Blocks как объекты, если я создаю два из них, а затем добавьте их в NSArray, есть ли способ их выполнить из массива?
int (^Block_001)(void) = ^{ return 101; };
int (^Block_002)(void) = ^{ return 202; };
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
РЕДАКТИРОВАТЬ: обновление для ясности. На @davedelong отличный ответ
int (^Block_001)(void) = [^{ return 101; } copy];
int (^Block_002)(void) = [^{ return 202; } copy];
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
[Block_001 release];
[Block_002 release];
Ответы
Ответ 1
Конечно, вы просто вызываете его с помощью ()
, как и любой другой блок, но вам нужно указать значение, которое вы извлекаете из NSArray
. Вот пример (с добавленным typedef, потому что в противном случае у меня болит голова):
typedef int (^IntBlock)(void);
IntBlock Block_001 = ^{ return 101; };
IntBlock Block_002 = ^{ return 202; };
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
int x = ((IntBlock)[array objectAtIndex:0]) (); // now x == 101
Ответ 2
@KennyTM и @David верны, но ваш код потенциально неверен. Вот почему:
При создании объекта NSArray
с объектами он будет retain
помещенными в него объектами. В случае блоков используется функция Block_retain
. Это означает, что массив сохранил блоки, которые вы создали, но которые живут в стеке (блоки являются одним из очень редких примеров объектов Objective-C, которые могут быть созданы в стеке, не вникая в абсурдные трюки). Это означает, что, как только этот метод выйдет, ваш массив теперь указывает на мусор, потому что блоки, которые он указывал на , больше не существуют. Чтобы сделать это правильно, вы должны сделать:
int (^Block_001)(void) = [^{ return 101; } copy];
int (^Block_002)(void) = [^{ return 202; } copy];
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
[Block_001 release];
[Block_002 release];
Вызывая copy
на блоке, вы явно перемещаете блок из стека и в кучу, где он может спокойно оставаться после выхода метода/функции. Затем, после добавления блоков в массив, вы должны сбалансировать свой copy
(из-за правила NARC) с последующим вызовом release
. Есть смысл?
Ответ 3
Конечно, вы можете.
int (^x)(void) = [array objectAtIndex:0];
printf("%d\n", x()); // prints 101.