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