- PVSM.RU - https://www.pvsm.ru -
Стиль или Суть
Сообщение или Носитель
Риторика или Диалектика
Красота — это нечто поверхностное или же идущее из глубинных истин?
Что значит «хороший дизайн»?
Эстетические суждения относительны или абсолютны?
Это важные вопросы, которые обсуждались философами, художниками и поэтами на протяжении тысячелетий.
И пока мы продолжаем наши поиски красоты и понимания мира, рынок мобильных приложений в данной области однозначно утверждает:
Пользователи платят за красивые приложения.
При покупке 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
через прокси является сложность определения списка методов, доступных для изменения. Поскольку +appearance
возвращает id
, Xcode не предоставляет соответствующую информацию при авто-подстановке.
Получить список методов, работающих с UIAppearance
можно поиском по заголовочным файлам [1]:
$ 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 [2]
Подобно тому, как NSLocalizedString
и #pragma
являются признаками качества Objective-C
кода, возможность управления внешним видом собственных UI компонентов через UIAppearance
является не только рекомендуемой практикой, но также демонстрирует определенный уровень заботы создателя компонента при его реализации.
В этой статье [3] демонстрируются некоторые нюансы реализации UIAppearance
в собственных компонентах. Она обязательна к прочтению для разработчиков, стремящихся создавать качественные UI компоненты.
Потенциальным недостатком UIAppearance
является то, что управление интерфейсом является императивным, а не декларативным, т.е. осуществляется во время выполнения программы, а не считывается из некого списка правил.
Это идея, пришедшая из веб-разработки — разделение содержимого и его представления. Что бы не говорилось про CSS, но таблицы стилей великолепно справляются с этой задачей.
Приверженцы таблиц стилей на iOS могут выбирать из нескольких альтернатив. Pixate [4] — коммерческий фреймворк, который использует CSS для стилизации приложений. NUI [5] — проект с открытым кодом, делает то же при помощи CSS/SCSS-подобного языка. Другой открытый проект той же направленности UISS [6] — позволяет настраивать UIAppearance
при помощи JSON.
Cocoa-программисты всегда были одержимы визуальной эстетикой и часто впадали в крайности в попытке достичь желаемого эффекта. Достаточно вспомнить Восхитительное Поколение [7] Mac-разработчиков и приложения типа Disco [8], которое выпускало виртуальный дым при записи дисков [9].
Дух перфекционизма жив и в iOS. Сообщество постоянно развивает систему в сфере пользовательского взаимодействия. Это делает разработку под iOS более сложной, но и гораздо более приятной.
Не соглашайтесь на полумеры.
Делайте свои приложения прекрасными от внешнего вида до реализации.
Автор: nsemchenkov
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ios/42865
Ссылки в тексте:
[1] по заголовочным файлам: http://stackoverflow.com/questions/9424112/what-properties-can-i-set-via-an-uiappearance-proxy
[2] список поддерживаемых свойств для iOS 6.1: https://gist.github.com/mattt/5135521
[3] этой статье: http://petersteinberger.com/blog/2013/uiappearance-for-custom-views/
[4] Pixate: http://www.pixate.com/
[5] NUI: https://github.com/tombenner/nui
[6] UISS: https://github.com/robertwijas/UISS
[7] Восхитительное Поколение: http://en.wikipedia.org/wiki/Delicious_Generation
[8] Disco: http://discoapp.com/
[9] выпускало виртуальный дым при записи дисков: http://www.youtube.com/watch?v=8Dwi47XOqwI
[10] Источник: http://habrahabr.ru/post/190858/
Нажмите здесь для печати.