Можете ли вы более подробно описать этот прокси-сервер и что ему нужно переслать?
Если ваш прокси-сервер должен перенаправить каждое сообщение на одну цель, он может сделать это в своем -forwardingTargetForSelector:
во время выполнения. Если нет (например, вам нужно перенаправить несколько целей или выполнить другие сложные манипуляции), вам необходимо реализовать -forwardInvocation:
для его обработки. Использование для обработки вызовов -forwardInvocation:
требует, чтобы вы реализовали -messageSignatureForSelector:
, потому что ему нужно получить подпись метода, чтобы иметь возможность создать вызов. (Даже если вы пересылаете его другому объекту, этот объект также должен либо реализовать метод напрямую, либо добавить метод в ответ на +resolveInstanceMethod:
, либо обрабатывать его с помощью -forwardInvocation:
, все из которых требуют, чтобы он также имел подпись.)
Подпись метода кодирует типы аргументов и тип возвращаемого значения. Причина, по которой эта информация необходима для вызова, заключается в том, что когда эти аргументы передаются, они выкладываются во время компиляции (возможно, последовательно) в памяти в соответствии с их типами в объявлении. Большой параметр struct будет занимать больше места, чем параметр int. Двойной также, вероятно, больше, чем int. Призыв должен хранить все эти аргументы и давать вам доступ или изменять их по индексу. Невозможно понять, как аргументы выставляются во время выполнения, если вы не знаете типы (или, по крайней мере, размеры типов).
Кроме того, механизм передачи сообщений отличаются для методов, которые возвращают структуры (они называют objc_msgSend_stret
) от других методов (они называют objc_msgSend
) (и на некоторых платформах, методы, которые возвращают двойники используют objc_msgSend_fpret
). В первом случае структура не возвращается напрямую, но местоположение для записи в передается как дополнительный аргумент указателя в качестве параметра out. Поэтому знание типа возврата также имеет решающее значение для обработки вызова и возвращаемого значения в вызове.
Даже если вы перенаправляете вызов другому объекту, в конечном итоге этот объект (или какой-либо объект, который он отправляет вниз по линии) должен каким-то образом знать подпись метода. Так почему бы не спросить этот объект для подписи селектора, когда он вам нужен?
Нет «безопасной» подписи, которая будет работать на все, потому что разные типы имеют разные размеры.