Как удалить методы экземпляра во время выполнения в Objective-C 2.0? - PullRequest
11 голосов
/ 22 августа 2009

Можно ли удалить методы, добавленные в класс, с помощью class_addMethod?

Или, если я хочу сделать это, я должен продолжать создавать классы во время выполнения с objc_allocateClassPair и добавлять к ним различные наборы методов, чтобы варьировать реализованные методы?

Я приму ответы, которые включают взлом: -)

Ответы [ 2 ]

15 голосов
/ 26 ноября 2011

Вы не можете точно «удалить» метод, но вы можете получить тот же эффект, что и удаление, заставив метод просто перенаправить все на путь пересылки сообщений (код, который в итоге вызовет -forwardInvocation:). Есть два способа сделать это:

  1. _objc_msgForward(), объявленный в /usr/include/objc/message.h, но не включенный в онлайн-документацию, может использоваться как IMP для вашего метода, который вы пытаетесь удалить. Поскольку он недокументирован, его можно считать закрытым или неподдерживаемым.
  2. Вы можете вызвать class_getMethodImplementation () с селектором, который, как вы знаете, не существует, и использовать результат как IMP для метода, который вы пытаетесь удалить. На основании документации это должно иметь тот же эффект, что и первый вариант:

Возвращенный указатель на функцию может быть функцией внутренней среды выполнения вместо фактической реализации метода. Например, если экземпляры класса не отвечают на селектор, возвращаемый указатель функции будет частью механизма пересылки сообщений во время выполнения.

В любом случае это становится так же просто, как:

method_setImplementation(methodToRemove, forwardingIMP);

Обратите внимание, что это в основном блокирует любые реализации суперкласса, поэтому вам нужно быть более осторожным, если у любого суперкласса может быть допустимая реализация, которую вы хотите сохранить. В таком случае вы можете получить IMP от суперкласса или что-то подобное.

10 голосов
/ 23 августа 2009

Короче, вы не можете.

Вы могли бы в Objective-C 1.0 ABI / API через:

OBJC_EXPORT void class_removeMethods(Class, struct objc_method_list *) OBJC2_UNAVAILABLE;

Но эта функция была удалена в Objective-C 2.0, потому что удаление методов почти никогда не является правильным ответом. Конечно, не достаточно часто, чтобы оправдать накладные расходы, связанные с поддержкой указанной функции.

Также из ObjC2.0 ABI была удалена возможность прямого доступа к структурам класса / метода. Теперь они непрозрачны, чтобы их можно было изменить в будущем, не нарушая бинарную совместимость.

Однако вы можете использовать собственный прокси, который меняет набор методов, на которые он реагирует. Смотрите документацию по классу NSProxy; http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSProxy_Class/Reference/Reference.html

Конечно, этот вопрос напрашивается на вопрос «Что вы пытаетесь сделать?». Такое на лету метапрограммирование нетипично. После создания экземпляра класса обычно нежелательно изменять набор методов, на которые он отвечает, исходя из предположения, что предыдущие экземпляры могут все еще зависеть от указанных методов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...