Как вызывается forwardInvocation:?

Глядя только на библиотеку времени выполнения Objective-C, когда сообщение отправляется объекту, который не отвечает на него, система времени выполнения дает получателю еще один шанс обработать сообщение. Таким образом, метод получателя forward::, если он реализован, вызывается. Однако, глядя на NSObject.mm, NSObject не похоже, не реализует forward::.

Итак, как же вызывается метод forwardInvocation: NSObject, поскольку единственное, что вызывает система среды выполнения, когда требуется переадресация, — это forward::? Использует ли Foundation objc_setForwardHandler (runtime.h) для установки новый обработчик, который вызывает forwardInvocation: всякий раз, когда сообщение, отправленное объекту NSObject, необходимо переслать?


person LuisABOL    schedule 02.03.2013    source источник


Ответы (2)


В какой-то момент давным-давно в среде выполнения Objective-C не было NSObject. Когда язык был впервые создан Брэдом Коксом и Томом Лавом, они добавили в него корневой объектный класс, названный Object. Это реализовало [Object forward::] , которое использовалось для пересылки сообщений.

Несколько лет спустя появился NextStep и внес свои собственные дополнения в язык, создав среду OpenStep (которая стала Cocoa). NextStep избавился от класса Object и заменил его на NSObject. Одним из внесенных изменений была замена метода forward:: на forwardInvocation. Класс Object все еще присутствует в исходном коде (как вы уже поняли), но я почти уверен, что он недоступен ни в iOS, ни в 64-битных приложениях OS X.

Вы правы, предполагая, что objc_setForwardHandler используется для обозначения того, что forwardInvocation следует использовать вместо forward:: для всех NSObjects. Боюсь, я не уверен, когда Фонд вызывает это... Я бы предположил, что инициализация NSObject. Я также не особо разбираюсь в базовой реализации среды выполнения, но, надеюсь, это хоть некоторо поможет?

person lxt    schedule 02.03.2013
comment
Согласно сообщению списка рассылки Apple примерно шестилетней давности (ссылка здесь) вы не можете использовать objc_setForwardHandler, если вы не работаете без основы. В теме, на которую я ссылался, может быть больше информации, которая может вам помочь. - person lxt; 03.03.2013
comment
Да, мне помогло. Теперь я уверен, что Foundation звонит objc_setForwardHandler, чтобы вызвать forwardInvocation. Если я вызову objc_setForwardHandler(NULL, NULL), который переопределит любой ранее установленный обработчик, будет вызван метод forward:: моего класса вместо forwardInvocation. Так что, скорее всего, при запуске Foundation вызывает objc_setForwardHandler, передавая IMP forwardInvocation в качестве аргументов. - person LuisABOL; 03.03.2013
comment
Вы бы так предположили. Я знаю, что Cocotron реализация Foundation с открытым исходным кодом делает это при NSObject инициализации (источник здесь). - person lxt; 03.03.2013
comment
Установка точки останова на objc_setForwardHandler показывает, что она вызывается из __CFInitialize в библиотеке CoreFoundation. - person Martin R; 03.03.2013
comment
но я почти уверен, что он недоступен ни в iOS, ни в 64-битных приложениях OS X. Что вы имеете в виду под недоступностью? - person user102008; 04.03.2013
comment
@ user102008 - он не включен ни в Foundation, ни во время выполнения. GCC также объявил его устаревшим и удалил все полезные методы из своей реализации в 2011 году. Если вы попытаетесь использовать Object для iOS или 64-битной OS X, вы получите сообщение об ошибке, и XCode перенаправит вас к NSObject документации. - person lxt; 04.03.2013

Этот сообщение SO содержит более подробный ответ на ваш вопрос о том, что происходит при отправке сообщения. к объекту, который не отвечает на него.

person Boon    schedule 09.04.2013