Стиль или Суть
Сообщение или Носитель
Риторика или Диалектика
Красота — это нечто поверхностное или же идущее из глубинных истин?
Что значит «хороший дизайн»?
Эстетические суждения относительны или абсолютны?
Это важные вопросы, которые обсуждались философами, художниками и поэтами на протяжении тысячелетий.
И пока мы продолжаем наши поиски красоты и понимания мира, рынок мобильных приложений в данной области однозначно утверждает:
Пользователи платят за красивые приложения.
При покупке iPhone, пользователь покупает также философию Apple: вещи должны не только хорошо работать, но и хорошо выглядеть. То же относится к разработке на iOS — некрасивый интерфейс пользователя сказывается и на программном коде.
Исторически даже для незначительного изменения внешнего вида приложения в iOS требовался набор хаков, сопряженных с опасностью отклонения приложения в AppStore. К счастью, начиная с iOS 5 у разработчиков есть новый инструмент: UIAppearance
.
UIAppearance
позволяет единообразно управлять стилем компонентов во всем приложении.
Для реализации этого с сохранением существующей структуры UIKit
специалисты Apple реализовали достаточно интересное решение: UIAppearance
— это протокол, предоставляющий прокси-объект, который используется для конфигурирования объектов конкретного класса. Почему именно прокси, а не свойство или метод самого UIView
? Потому что существуют объекты, не входящие в иерархию UIView
, такие как UIBarButtonItem
, со своим собственным представлением. Внешний вид может быть изменен у всех компонентов определенного типа или только у привязанных к специфической иерархии:
+appearance
возвращает прокси-объект для данного класса элементов.+appearanceWhenContainedIn:(Class <UIAppearanceContainer>)ContainerClass,...:
возвращает прокси-объект для объектов, находящихся в определенном контейнере.
Для управления внешним видом всех объектов класса, нужно использовать прокси-объект, связанный с этим классом. Например, чтобы изменить цвет всех объектов UINavigationBar
:
[[UINavigationBar appearance] setTintColor:myColor];
Для того, чтобы изменить внешний вид объектов определенного класса в заданном контейнере — используйте метод appearanceWhenContainedIn:
:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
setTintColor:myNavBarColor];
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], [UIPopoverController class], nil]
setTintColor:myPopoverNavBarColor];
[[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil]
setTintColor:myToolbarColor];
[[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], [UIPopoverController class], nil]
setTintColor:myPopoverToolbarColor];
Определение свойств, доступных через UIAppearance
Важной проблемой работы UIAppearance
через прокси является сложность определения списка методов, доступных для изменения. Поскольку +appearance
возвращает id
, Xcode не предоставляет соответствующую информацию при авто-подстановке.
Получить список методов, работающих с UIAppearance
можно поиском по заголовочным файлам:
$ cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk/System/Library/Frameworks/UIKit.framework/Headers
$ grep -H UI_APPEARANCE_SELECTOR ./* |sed 's/ __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0) UI_APPEARANCE_SELECTOR;//'
UIAppearance
завязан на наличие макроса UI_APPEARANCE_SELECTOR
в определении метода. Любой метод с подобной пометкой может быть использован при работе через прокси.
Вот, для удобства, список поддерживаемых свойств для iOS 6.1
Реализация UIAppearance в собственных компонентах
Подобно тому, как NSLocalizedString
и #pragma
являются признаками качества Objective-C
кода, возможность управления внешним видом собственных UI компонентов через UIAppearance
является не только рекомендуемой практикой, но также демонстрирует определенный уровень заботы создателя компонента при его реализации.
В этой статье демонстрируются некоторые нюансы реализации UIAppearance
в собственных компонентах. Она обязательна к прочтению для разработчиков, стремящихся создавать качественные UI компоненты.
Альтернативные решения
Потенциальным недостатком UIAppearance
является то, что управление интерфейсом является императивным, а не декларативным, т.е. осуществляется во время выполнения программы, а не считывается из некого списка правил.
Это идея, пришедшая из веб-разработки — разделение содержимого и его представления. Что бы не говорилось про CSS, но таблицы стилей великолепно справляются с этой задачей.
Приверженцы таблиц стилей на iOS могут выбирать из нескольких альтернатив. Pixate — коммерческий фреймворк, который использует CSS для стилизации приложений. NUI — проект с открытым кодом, делает то же при помощи CSS/SCSS-подобного языка. Другой открытый проект той же направленности UISS — позволяет настраивать UIAppearance
при помощи JSON.
Cocoa-программисты всегда были одержимы визуальной эстетикой и часто впадали в крайности в попытке достичь желаемого эффекта. Достаточно вспомнить Восхитительное Поколение Mac-разработчиков и приложения типа Disco, которое выпускало виртуальный дым при записи дисков.
Дух перфекционизма жив и в iOS. Сообщество постоянно развивает систему в сфере пользовательского взаимодействия. Это делает разработку под iOS более сложной, но и гораздо более приятной.
Не соглашайтесь на полумеры.
Делайте свои приложения прекрасными от внешнего вида до реализации.
Автор: nsemchenkov