Выполнение блоков от NSArray?

Я просто думал, поскольку можно рассматривать Блоки как объекты, если я создаю двух из них и затем добавляю их к 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];
37
задан fuzzygoat 16 September 2011 в 21:38
поделиться

3 ответа

Конечно, вы просто вызываете его с помощью () , как и любой другой блок, но вам нужно привести значение, полученное из 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
29
ответ дан 27 November 2019 в 04:18
поделиться

Конечно, можете.

int (^x)(void) = [array objectAtIndex:0];
printf("%d\n", x()); // prints 101.
7
ответ дан 27 November 2019 в 04:18
поделиться

@KennyTM и @David правы, но ваш код потенциально неверен. Вот почему:

При создании NSArray с объектами, он будет сохранять объекты, помещенные в него. В случае с блоками для этого используется функция 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. Имеет смысл?

60
ответ дан 27 November 2019 в 04:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: