Создание IMP от блока Objective C

С точки зрения CLR C# статический класс просто "изолируется" и "абстрактный" класс. Вы не можете создать экземпляр, потому что это абстрактно, и Вы не можете наследоваться ему, так как это изолируется. Остальное - просто некоторое волшебство компилятора.

19
задан Jonathan Sterling 20 January 2012 в 06:27
поделиться

1 ответ

Поскольку это было написано, теперь в iOS есть API и 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. Реальный код будет похож, но, вероятно, немного отличаться.

  • [копия блока реализации] критична; Блоки начинают жизнь в стеке (обычно)

27
ответ дан 30 November 2019 в 03:34
поделиться