Я предполагал, что могу отправить сообщение объекту, и оно будет вызывать его независимо от того, было оно там или нет.
Вы действительно можете отправить любое сообщение любому объекту;это часть веселья Objective-C.Тип переменной (Foo *
, Bar *
, id
или любой другой) не влияет на отправку сообщения.Объект, на который указывает переменная, знает свой класс.Поиск соответствующего метода выполняется во время выполнения через этот класс.Компилятор превращает выражение в скобках в вызов функции: objc_msgSend
.
При сборке вы должны получить предупреждение о [object myString]
, говоря: «Foo» может не отвечатьto 'myString' "- компилятор знает, что где-то есть хотя бы один класс, у которого есть метод, соответствующий myString
, и он знает, что во время компиляции Foo
, похоже, не является одним из них,но это не может гарантировать, что Foo
не сможет что-то сделать с сообщением во время выполнения.Сообщения могут быть разрешены пользовательскими способами во время выполнения .Обратите внимание, что если вы измените тип переменной на id
, предупреждение исчезнет - компилятор больше не сможет рассуждать о том, какие методы доступны.
Если окажется, что объект, на который вы отправляете myString
не не отвечает (т. Е. Если объект действительно a Foo
вместо Bar
или один из подклассов Foo
, который нереализовать myString
), будет сгенерировано исключение.Это ответ по умолчанию (от всего, что наследуется от NSObject
) на нераспознанное сообщение.
Если у вас есть разнородная коллекция объектов, на которые вам нужно отправлять сообщения, вы, вероятно, захотите проверить каждый объектпервый.Вы можете сделать так, как предложил jstevenco, и проверить работоспособность:
if( [object respondsToSelector:@selector(myString)] ){
или проверить личность:
if( [object isKindOfClass:[Bar class]] ){
Последний пройдет, если объект является Bar
или любым изПодклассы Bar
.Используйте isMemberOfClass:
для проверки только для указанного вами класса.