После завершения загрузки nib-файла его экземпляры являются абсолютно полноценными; они инициализированы и настроены с помощью всех атрибутов, указанных в окнах инспекторов атрибутов и размеров, а их выводы были использованы для задания значений соответствующих переменных экземпляров.

Тем не менее программист может добавить свой код для процесса инициализации из загружаемого nib-файла. В этом разделе мы опишем, как это сделать.

Мы применим привычный подход, в рамках которого контроллер представления, функционирующий как владелец загружаемого nib-файла, содержащего его главное представление (а значит, представленный в nib-файле прокси-объектом владельца nib-файла), имеет выход к объекту интерфейса, созданного с помощью nib-файла. В этой архитектуре контроллер представления может выполнять дальнейшую настройку объекта интерфейса, потому что он имеет ссылку на него после загрузки nib-файла. Прежде всего мы можем сделать это с его методом viewDidLoad. Это объясняется тем, что мы уже использовали метод viewDidLoad как место для вставки кода, изменяющего заголовок “Howdy! ” на “Hi ! ”.

Другая возможность — конфигурировать сам nib-объект в дополнение к его настройке в nib-файле. Часто это делают из-за желания использовать готовый подкласс объекта интерфейса. В принципе программист может сам написать такой подкласс, чтобы создать место для самонастройки кода. Дело в том, что nib-редактор не позволяет выполнять конфигурирование после загрузки nib-файла. Кроме тогр, может существовать много объектов, которые конфигурируются одинаково и сложно, поэтому имеет смысл предоставить им возможность конфигурироваться самостоятельно с помощью общего подкласса, а не конфигурировать их индивидуально в nib-редакторе.

Например, в пользовательском классе можно реализовать сообщение awakeFromNib. Оно рассылается всем объектам, созданным на основе nib-файла, сразу после их создания при загрузке nib-файла the object has been initialized and configured and its connections are operational.

Например, пусть фон кнопки всегда будет красным, независимо от того, как она сконфигурирована в nib-файле. (Это довольно необычно, но очень эффективно.) Создадим в проекте Empty Window подкласс кнопки MyRedButton.

1. В навигаторе проекта выберите команду File^New^File. Выберите класс IOS Cocoa Touch Objective-C и щелкните на кнопке Next.

2. Назовите новый класс MyRedButton. Создайте подкласс класса UIButton и щелкните на кнопке Next.

3. Сохраните файл в папке проекта в группе Empty Window и выберите целевое приложение Empty Window. Щелкните на кнопке Create. Среда Xcode создает файлы MyRedButton.h и MyRedButton.m.

4. В файле MyRedButton. m в разделе реализации вставьте следующие строки:

awakeFromNib:- (void) awakeFromNib {

[super awakeFromNib];

self.backgroundColor = [UlColor redColor];

}

Теперь у нас есть подкласс UIButton, который при создании объекта кнопки из nib-фай-ла делает ее фон красным. Однако ни в одном nib-файле у нас нет ни одного экземпляра этого подкласса. Исправим это. Откройте раскадровку, выберите кнопку и используйте инспектор идентичности для изменения класса кнопки на MyRedButton.

Теперь соберите и выполните проект. Убедитесь сами, кнопка стала красной!

 

Предупреждение для программистов в системе OS X

Если вы опытный программист в системе OS X, то, возможно, привыкли к тому, что метод super редко или никогда не вызывается из метода awake FromNib; это вызывает исключение. В системе iOS вы всегда должны вызывать метод super в методе awakeFromNib. Другое важное отличие от системы OS X состоит в том, что владелец awakeFromNib вызывается во время загрузки nib-файла, поэтому существует возможность, что объект будет посылать сообщение awakeFromNib много раз. В системе iOS сообщение awake FromNib посылается объекту только один раз, когда этот объект создается из nib-файла.

 

Еще одна возможность — воспользоваться преимуществами атрибутов User Defined Runtime Attributes в окне инспектора идентичности nib-файла. Это позволяет посылать сообщение setValue: forKey: объекту во время его создания из nib-файла. (На самом деле это сообщение setValue: forKeyPath:; ключевые пути (key paths) обсуждаются в главе 12.) Это позволяет конфигурировать в nib-редакторе аспекты nib-объекта, для которых в nib-pe-дакторе нет встроенного интерфейса. Естественно, объект должен быть готов к реакции на заданный ключ, иначе ваше приложение при загрузке nib-файла завершится аварийно.

Например, один из недостатков nib-редактора заключается в том, что он не позволяет конфигурировать атрибуты уровня. Допустим, мы хотим с помощью nib-редактора закруглить углы нашей красной кнопки. Для этого в коде можно задать настройку кнопки layer. cornerRadius. Nib-редактор не дает доступа к этому свойству. Вместо этого мы можем выбрать кнопку в nib-редакторе и использовать раздел User Defined Runtime Attributes. Установим атрибут Key Path равным layer. cornerRadius, атрибут Type равным Number, а атрибут Value равным значению, которое мы хотим, — 10 (рис. 7.15). Соберите и выполните приложение; убедитесь, что углы кнопки теперь закруглены.

Для того чтобы вмешаться в процесс инициализации nib-объекта еще раньше, если объект относится к классу UlView (или его подклассу) или UlViewController (или его подклассу), можно реализовать метод initWithCoder:. Обратите внимание на то, что метод initWithCoder: не является стандартным инициализатором, предусмотренным шаблоном; вместо него в подклассе UlView есть метод initWithFrame:. Например, наш класс MyRedButton содержит шаблонный метод initWithFrame:. Однако это не дает нам никакой выгоды, потому что метод initWithFrame : не вызывается при создании объекта класса

UlView во время загрузки nib-файла, а вместо него вызывается метод initWithCoder:. (Новички часто делают типичную ошибку — реализуют метод initWithFrame:, а затем пытаются понять, почему их код не работает при создании представления из nib-файла.)

Возможная причина для реализации метода initWithCoder: совпадает с обоснованием для реализации любого другого инициализатора — для инициализации дополнительного экземпляра, объявленного в вашем подклассе. Структура метода initWithCoder: типична для любого инициализатора (см. главу 5): сначала вызывается метод super, а в конце возвращается объект self.

- (id) initWithCoder:(NSCoder *)aDecoder { self * [super initWithCoder:aDecoder]; if (self) {

self->_mylvar = // whatever

return self;

}

 

Закругление углов кнопки с помощью атрибута в ходе выполнения приложения 

Puc. 7.15. Закругление углов кнопки с помощью атрибута в ходе выполнения приложения

 


 

 

 

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