С тех пор, как это было написано, в iOS и Mac OS X теперь есть API, который позволяет напрямую превращать блоки в IMP. Я написал пост в блоге с описанием API (imp_implementationWithBlock ()).
<Ч />
Блок - это, по сути, структура, которая содержит бит метаданных, ссылку на код, содержащийся в блоке, и копию const-скопированных данных, захваченных в блоке.
Таким образом, нет, невозможно напрямую отобразить между 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) реализовать батутный ИМП примерно так:
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. Реальный код будет похожим, но, вероятно, немного другим.
критически важна [копия реализации]; Блоки начинают жизнь в стеке (обычно)