Каждый класс наследует от класса NSOb j ect, и поэтому здесь имеет смысл уделить немного места его исследованию, чтобы стало понятнее, как им пользоваться. Класс NSOb ject имеет довольно сложное строение. Ниже перечисляются некоторые особенности его поведения.

 

  • Определение некоторых собственных методов класса и методов экземпляра, имеющих в основном отношение к основным операциям получения экземпляров отправки методов и разрешения (см. документацию NSObject Class Reference).
  • Принятие протокола класса NSObject. В этом протоколе объявляются методы экземпляра, имеющие в основном отношение к управлению памятью, взаимосвязи экземпляра с его классом и интроспекции. Протокольные методы из класса NSObject являются обязательными, и поэтому все они реализуются в этом классе, (см. документацию NSObject Class Reference). Такая архитектура позволяет сделать класс NSProxy корневым, а также принять протокол класса NSObject.
  • Реализация служебных методов, связанных с протоколами NSCopying, NSMutable Copying и NSCoding, без формального принятия этих протоколов. Они не приняты в классе NSObject намеренно, поскольку это привело бы к необходимости принять их во всех остальных классах, что было бы неверно. Благодаря именно такой архитектуре можно вызвать соответствующий служебный метод, если в классе все же принят один из этих протоколов. Например, в классе NSObject реализуется метод экземпляра сору, что позволяет вызвать его для экземпляра любого класса. Если в классе не принят протокол NSCopying и не реализован метод copyWithZone:, то исход подобной операции будет неудачным.
  • Применение более десятка категорий, распределенных по различным заголовочным файлам, в классе NSObject для внедрения в нем большого числа методов. Например, метод awakeFromNib, упоминавшийся в главе 7, происходит из категории UINibLoadingAdditions класса NSObject, объявленной в заголовочном файле UINibLoading.h. Метод performSelector:withObject:afterDelay:, рассматриваемый в главе 11, происходит из категории NSDelayedPerforming класса NSOb j ect, объявленной в заголовочном файле NSRunLoop. h.
  • Наследование. Как пояснялось в главе 4, объект класса является объектом. Следовательно, все классы, объекты которых относятся к типу Class, наследуют от класса NSObject. Это означает, что любой метод, определенный в классе NSObject, может быть вызван для объекта класса как метод этого класса! Например, метод respondsToSelector: определен в классе NSObject как метод экземпляра, а следовательно, его можно также рассматривать как метод класса и отправлять объекту класса.

Затруднение для программиста состоит в том, что в документации, предоставляемой компанией Apple, очень жестко регламентирована классификация. Если вы пытаетесь выяснить, что же можно сообщить объекту, то вас интересует не происхождение методов этого объекта, а только то, что можно сообщить этому объекту. В документации методы различаются по их происхождению. Хотя класс NSObject является корневым и самым важным классом, от которого наследуют все остальные классы, тем не менее ни на одной из страниц документации не предоставляется краткий обзор всех его методов. Вместо этого приходится одновременно обращаться к документации NSObject Class Reference и NSObject Protocol Reference, а также к страницам документации с описанием протоколов NSCopying, NSMutableCopying и NSCoding, чтобы понять, каким образом они взаимодействуют с методами, определенными в классе NSOb j ect. Ведь нужно еще мысленно предоставить свой вариант метода класса для каждого метода экземпляра из класса NSOb j ect!

Кроме того, имеются методы, внедренные в класс NSObject по категориям. Методы наиболее общего характера описаны на отдельных страницах документации на класс NSOb j ect. Например, метод cancelPreviousPerformRequestsWithTarget: происходит из категории, объявленной в заголовочном файле NSRunLoop.h. Тем не менее он описывается (и совершенно справедливо) в документации на класс NSObject, поскольку это метод данного класса, а следовательно, он, по существу, является глобальным методом, который можно отправить в любой момент.

Остальные являются методами делегата, применяются в ограниченных случаях (а на самом деле считаются формальными протоколами) и поэтому не требуют централизованной документации. Например, метод animationDidStart: описывается (и совершенно справедливо) в документации на класс CAAnimation, поскольку о нем нужно знать только в том случае, если приходится иметь дело с классом CAAnimation. Однако каждый объект реагирует на метод awakeFromNib и, скорее всего, имеет большое значение для каждого разрабатываемого приложения. Тем не менее для ознакомления с его функциями приходится переходить от документации на класс NSObject к поискам на страницах документации NSObject UIKit Additions Reference, где вряд ли можно обнаружить его описание! Это же относится (можно с уверенность утверждать) и ко всем методам доступа к значениям по ключам (см. главу 12), а также к методам наблюдения за значениями по ключам (см. главу 13).

Итак, собрав вместе, так или иначе, все методы класса NSOb j ect, вы обнаружите, что они подпадают под определенную естественную классификацию, как в основном и описывается в документации, предоставляемой компанией Apple (см. также разделы “The Root Class” и “Cocoa Objects” документации Cocoa Fundamentals Guide). Ниже приведена эта классификация методов класса NSObject.

Создание, разрушение и управление памятью

К этой категории относятся методы для создания экземпляра, например, alloc и сору; методы, которые можно заместить, чтобы выяснить что-нибудь происходящее в течение срока действия объекта, например initialize (см. главу 11) и dealloc (см. главу 12); а также методы для управления памятью (см. главу 12).

Отношения между классами

К этой категории относятся методы, позволяющие выяснить класс объекта и наследование, например class, superclass, isKindOfClass: и isMemberOfClassДля проверки класса экземпляра (или класса) служат такие методы, как isKindOfClass: и isMemberOfClass:. Прямое сравнение объектов двух классов редко рекомендуется, как, например, в следующем выражении:

[someObject class] == [otherObject class]

Дело в том, что класс экземпляра в среде Cocoa может быть закрытым, недокументированным подклассом ожидаемого класса. Об этом упоминалось ранее в связи с кластерами классов, но подобная ситуация может возникнуть и в других случаях.

Интроспекция и сравнение объектов.

К этой категории относятся методы, позволяющие выяснить, что произойдет, если объекту будет послано сообщение (например, respondsToSelector:); представить объект в виде символьной строки (метод description, применяемый при отладке кода; см. главу 9); а также сравнить объекты (isEqual:).

Реагирование на сообщения

К этой категории относятся методы, позволяющие выяснить, что происходит, когда объекту посылается определенное сообщение (например, doesNotRecognizeSelector:). Подробнее об этом можно узнать из документации Objective-C Runtime Programming Guide.

Отправка сообщений

К этой категории относятся методы, предназначенные для отправки сообщений в динамическом режиме. Например, метод performSelector: принимает селектор в качестве параметра и, оправляя его объекту, сообщает ему, что он должен выполнить этот селектор. На первый взгляд, это похоже на отправку сообщения данному объекту, но что, если вплоть до времени выполнения неизвестно, какое именно сообщение следует посылать? Имеются также варианты метода performSelector:, позволяющие отправить сообщение в отдельно указанном потоке или по истечении определенного промежутка времени (performSelector: withOb ject :afterDelay: и подобные методы).


 

 

 

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