Тип IMP
в Objective-C представляет собой указатель на функцию, насколько я понимаю. Есть ли способ сделать IMP
из указателя блока? Спасибо за ваши идеи.
Создание IMP из блока Objective-C
Ответ 1
Поскольку это было написано, теперь есть API в iOS и Mac OS X, который позволяет Блокам напрямую превращаться в IMP. Я написал сообщение в блоге, описывающее API (imp_implementationWithBlock()).
Блок эффективно представляет собой структуру, которая содержит бит метаданных, ссылку на код, содержащийся в блоке, и копию данных, скопированных с помощью константы, захваченных внутри блока.
Таким образом, нет, нет прямого способа сопоставления между IMP
и ссылкой на блок.
Когда вызов блока компилируется, компилятор испускает батут, который устанавливает фрейм стека, а затем переходит к исполняемому коду внутри блока.
Что вы можете сделать, тем не менее, создать IMP, который действует как этот батут. Для следующего вам понадобится один конкретный IMP для каждого набора аргументов и возвращаемых типов для вызова. Если вам нужно сделать это общее, вам нужно будет использовать сборку.
Для этого я настраиваю уникальные экземпляры блоков на экземпляр класса. Если вы хотите иметь общий блок, который действует во всех экземплярах, создайте хэш из SEL
→ блока для каждого класса.
(1) Связать блоки, чтобы действовать как IMP, используя связанный механизм ссылок. Что-то вроде:
void (^implementingBlock)(id s, SEL _c, int v) = ^(id s, SEL _c, int v) {
// do something here
}
objc_setAssociatedObject(obj, SELToImp, [implementingBlock copy]));
(2) реализовать трамплин IMP примерно так:
void void_id_sel_intTramp(id self, SEL _cmd, int value) {
int (^block)(id s, SEL _c, int v) = objc_getAssociatedObject(self, _cmd);
block(self, _cmd, value);
}
(3) введите вышеприведенный трамплин для любого селектора через API-интерфейс Objective-C (см. method_setImplementation
и т.п.)
Предостережения:
-
это было введено в StackOverflow. Реальный код будет похож, но, вероятно, немного отличается.
-
критика [implementationBlock] имеет решающее значение; Блоки начинают жизнь в стеке (обычно)
Ответ 2
Я считаю, что Майк Эш с некоторой помощью Лэндона Фуллера решил это для общего дела, в том числе iOS, что сложнее. У него есть класс на github, который превратит блок в указатель функции.
Вы также можете пригласить объявление и некоторое интересное последующее обсуждение cocoa -unbound.
ОБНОВЛЕНИЕ: И теперь есть imp_implementationWithBlock()
, как указано выше.