Вопрос

Тот Самый 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 () , как указано выше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top