Во встроенном классе Cocoa можно определить методы, которые эта среда будет вызывать сама и которые желательно (или обязательно) заместить в подклассе. Это обусловливает специальное, а не только стандартное поведение прикладного кода.

В главе 10 был приведен пример, в котором представление типа UlView воспроизводилось с помощью метода drawRect:. Это был пример так называемого функционального события. Замещая метод drawRect: в подклассе, производном от класса UlView, можно предписать целую процедуру для воспроизведения представления. Точно неизвестно, когда именно этот

метод будет вызван, да это и не важно, но когда он все же будет вызван, представление воспроизведется. Это гарантирует, что представление всегда будет выглядеть именно так, как требуется. (Для этого совсем не обязательно вызывать метод drawRect: самостоятельно. Достаточно вызвать метод setNeedsDisplay и предоставить среде Cocoa возможность самой вызвать метод drawRect: в ответ.)

Встроенные в класс UlView подклассы могут иметь и другие методы функциональных событий, которые потребуется специально настроить путем наследования. Как правило, это требуется для того, чтобы изменить способ воспроизведения представления, не возлагая на себя все бремя самостоятельного выполнения процедуры воспроизведения. В главе 10 был приведен пример воспроизведения надписи на метке типа UILabel с помощью метода drawTextlnRect:. Аналогичным примером служит воспроизведение ползунка типа UI Slider, где имеется возможность специально настроить положение и размер бегунка, перемещающегося по шкале ползунка, заместив метод thumbRectForBounds: trackRect: value:.

Класс UlViewController служит подходящим примером для наследования. Среди методов, перечисленных в документации на класс UlViewController, следует прежде всего отметить те, для замещения которых могут возникнуть веские основания. Если создать в среде Xcode подкласс, производный от класса UlViewController, то можно обнаружить, что в шаблон уже входят два замещенных метода, с которых можно начать разработку нового подкласса. Например, метод viewDidLoad вызывается, чтобы уведомить о том, что представление контроллера загружено, а следовательно, можно приступить к инициализации. Это вполне очевидный пример события времени действия.

Такой метод из класса UlViewController, как supportedlnterfaceOrientations, относится к так называемым запросным событиям. В этом случае из прикладного кода нужно возвратить битовую маску, сообщающую среде Cocoa, в какой ориентации представление может оказаться в определенный момент времени, когда бы он ни настал. Обязанность вызвать этот метод в подходящие моменты времени доверяется среде Cocoa, и если пользователь повернет мобильное устройство, то интерфейс приложения должен или не должен соответственно изменить свою ориентацию в зависимости от значения, возвращаемого из прикладного кода.

В поисках событий, которые можно получать через наследование, непременно проследите отношения между классами вверх по иерархии наследования. Так, если вам нужно выяснить, как получить уведомление, когда специальный подкласс, производный от класса UILabel, будет встроен в другое представление, вы найдете ответ в документации на класс UILabel. Этот класс получает соответствующее событие в силу того, что он является производным от класса UlView. Из документации на класс UlView можно узнать, что метод didMoveToSuperview можно заместить, чтобы получить уведомление о наступлении данного события.

Следуя дальше вверх по иерархии наследования, вы обнаружите, например, метод initialize класса NSObject. Прежде чем любой класс сможет отправить свое первое сообщение класса, включая получение экземпляра, отправляется сообщение initialize. Следовательно, метод initialize можно инициализировать, чтобы выполнить код как можно раньше в течение срока действия класса. Так, в проекте Empty Window экземпляр класса делегата AppDelegate получается очень рано во время действия приложения, и поэтому его метод initialize может послужить удобным местом для выполнения инициализации как можно раньше в приложении, например, для установки по умолчанию значений любых пользовательских настроек.

Реализуя метод initialize, необходимо попутно проверить, указывается ли ссылка self на интересующий класс, иначе метод initialize может быть вызван снова, а следовательно, прикладной код будет выполнен повторно, если используется подкласс, производный

от данного класса. Это один из тех немногих случаев, когда два класса сравниваются друг с другом непосредственно, как показано ниже. Поскольку метод initialize является методом класса, то ссылка self, по существу, означает класс, которому было отправлено сообщение initialize.

// MyClass.ш:

+ (void)initialize {

if (self == [MyClass class]) (

// сделать что-нибудь

}

)


 

 

 

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