Ответ 1
Причина № 1: Плохой стиль - он избыточный и нечитаемый.
Компилятор автоматически генерирует вызовы objc_msgSend()
(или их вариант) при обнаружении выражений Objective-C сообщений. Если вы знаете, что класс и селектор должны быть отправлены во время компиляции, нет причин писать
id obj = objc_msgSend(objc_msgSend([NSObject class], @selector(alloc)), @selector(init));
вместо
id obj = [[NSObject alloc] init];
Даже если вы не знаете класс или селектор (или даже оба), он по-прежнему безопаснее (по крайней мере, у компилятора есть шанс предупредить вас, если вы делаете что-то потенциально неприятное/неправильное), чтобы получить правильно напечатанную указатель функции к самой реализации и вместо этого используйте этот указатель функции:
const char *(*fptr)(NSString *, SEL) = [NSString instanceMethodForSelector:@selector(UTF8String)];
const char *cstr = fptr(@"Foo");
Это особенно актуально, когда типы аргументов метода чувствительны к промоакциям по умолчанию - если они есть, то вы не хотите передавать их через переменные аргументы objc_msgSend()
, потому что ваша программа будет быстро вызывать undefined.
Причина № 2: опасная и подверженная ошибкам.
Обратите внимание на часть "или какой-либо вариант" в # 1. Не все сообщения отправляются с помощью самой функции objc_msgSend()
. Из-за сложностей и требований в ABI (в частности, в вызывающем соглашении функций) существуют отдельные функции для возврата, например, значений или структур с плавающей запятой. Например, в случае метода, который выполняет какой-то поиск (подстроки и т.д.), И возвращает структуру NSRange
, в зависимости от платформы, может потребоваться использовать возвращающую структуру версию сообщения функция:
NSRange retval;
objc_msgSend_stret(&retval, @"FooBar", @selector(rangeOfString:), @"Bar");
И если вы ошибаетесь (например, вы используете неподходящую функцию мессенджера, вы смешиваете указатели с возвращаемым значением и self
и т.д.), ваша программа, вероятно, будет вести себя неправильно и/или сбой. ( И вы, скорее всего, ошибаетесь,, потому что это даже не так просто - не все методы, возвращающие struct
, используют этот вариант, поскольку небольшие структуры будут вписываться в один или два регистра процессора, исключая нужно использовать стек как место возвращаемого значения. Поэтому, если вы не хардкорный хакер ABI, вы скорее хотите, чтобы компилятор выполнял свою работу, или там были драконы.)