Предыдущие разделы вращалась вокруг того факта, что Objective-C до времени выполнения не знает, какому объекту посылается сообщение.

Но справедливо большее: Objective-C до времени выполнения не должен знать, какое сообщение отправляется объекту. Некоторые важные методы в действительности принимают в качестве параметров и сообщение, и его получателя; они не собраны и использованы для формирования выражения фактическое сообщение до времени выполнения.

Рассмотрим, например, такое объявление метода из класса NSNotificationCenter Cocoa:

- (void)addObserver:(id)notificationObserver
selector:(SEL)notificationSelector
name:(NSString *)notificationName
object:(id)notificationSender

Позже (в главе 11) я поясню, что делает этот метод. Сейчас для понимания важно то, что он составляет команду для отправки некоторого сообщения определенному объекту позже, в подходящее время. Например, наша цель при вызове этого метода может заключаться в том, чтобы иметь сообщение tickleMeElmo: для отправки позже объекту myObject. Для этого нам надо передать соответствующие данные в качестве двух первых аргументов.

Давайте рассмотрим, какие аргументы следует передать. Первый параметр (observer:) представляет собой объект, которому будет отправлено сообщение и который имеет тип id, что позволяет указать в качестве получателя объект любого типа. Так что в нашем случае в

качестве аргумента observer: мы передаем myObject. Само сообщение представляет собой параметр selector:, который имеет специальный тип данных SEL. Теперь вопрос заключается в том, как выразить имя сообщения tickleMeElmo:.

Вы не можете просто набрать tickleMeElmo: как обычный текст: это не сработает синтаксически. Вы можете подумать, что сообщение можно выразить как строку NSString, т.е. как @"tickleMeElmo: ", но это тоже не сработает. Оказывается, корректно следует поступить следующим образом:

@selector (tickleMeElmo:)

Текст @selector() представляет собой директиву компилятору, которая говорит о том, что то, что находится в круглых скобках, представляет собой имя сообщения. Обратите внимание, что находящееся в скобках не является NSString; это просто имя сообщения. А поскольку это имя, оно не должно включать пробелы и должно включать в качестве своей части двоеточия.

Так что правило исключительно простое: там, где ожидается SEL, вы обычно передаете выражение Sselector. Ошибка в этом синтаксисе достаточно распространена среди начинающих программистов.

К сожалению, этот синтаксис — также прямое приглашение наделать ошибок при вводе, возможно, с очень неприятными результатами. Если myObject реализует метод tickleMeElmo:, а я случайно наберу текст, скажем, ©selector (tickleMeElmo), забыв о двоеточии, то даже если сообщение tickleMeElmo без двоеточия будет отправлено объекту myObject, приложение, вероятно, все равно завершится аварийно из-за исключения нераспознанного селектора.

В Xcode 5, впервые в истории Objective-C, введено предупреждение компилятора в случае, когда селектор не соответствует известному методу (“Undeclared selector ‘tickleMeElmo”’). Таким образом, вы можете быть предупреждены о возможности будущего аварийного завершения — или нет. Компилятор не может заглянуть в класс аргумента observer: и выяснить, реализован ли в нем данный метод. Вместо этого компилятор предупреждает только в ситуации, если класса с данным методом вообще нет. Справедливо и обратное: если компилятор знает о наличии метода tickleMeElmo в каком-то классе, то никакого предупреждения вы не получите, даже если объект, которому в действительности во время работы программы будет послано сообщение tickleMeElmo, такого метода не имеет.


Похожие статьи

 

 

 

Добавить комментарий