Подходы к реализации UI в Swift
Всем привет, меня зовут Дима, и я iOS-разработчик 👨🏻💻. Сегодня хотел поделиться способами реализации UI в iOS.
Дело в том, что во всех проектах, в разработке которых я принимал участие, UI создавался по-разному. И это при том, что вариантов всего три: Xib, Storyboards и кодинг 😅 Давайте разберемся, в чем их основные особенности. Для начала, я опишу каждый из инструментов:
XIB:
XIB расшифровывается как XML Interface Builder. Такие файлы внутри себя хранят вью, лейауты и значения, описанные на xml. По сути своей это иерархический набор описаний объектов. Такой XIB файл компилируется в бинарный Nib файл. Nib файл, соответственно, уже нельзя открыть в Interface Builder. Именно он будет включен в ваше собранное приложение в том виде, в котором он скомпилировался из XIB. Это, кстати, причина, почему, когда вы вызываете в коде инстанс View, описанной на XIBах, вы обращаетесь к NIB.
Storyboard:
Это, как предлагает Apple, post-XIB, по сути, более удобный способ программирования UI в IB. Под капотом у него все тот же xml с той же компиляцией в nib файлы. Однако, на сторибордах отображается представление UI через показ экранов( а не одного элемента, который можно было сделать в XIB), контента этих экранов и, что мне больше всего импонирует, возможность визуализации флоу пользовательского сценария. Особенно на проектах, где аналитика описана через диаграммы взаимодействия с экранами, одно удовольствие перенести это на флоу в сториборды и разбить по юзкейсам.
Code
Программирование UI элементов через код, соответственно без компиляции в nib, а напрямую в .o файлы, людям, которые до этого создавали UI через графические инспекторы, кажется сложнее, чем перетаскивание квадратиков, но, набив руку, это становится очень увлекательным занятием, в котором сразу же подсвечивается огромное количество плюсов (о них позже). Пока выделим два момента:
1. Все, что можно создать через графические интерфейсы, можно создать в коде, наоборот не работает :)
2. Переиспользование юай элементов становится намного проще.
Супер! Теперь, когда мы прошлись по каждому из основных инструментов создания пользовательского интерфейса, давайте определимся, в каких случаях будет лучше использовать тот или иной способ. Лично я сторонник того, что универсального ответа нет, а поэтому предлагаю подойти к вопросу, разобрав плюсы и минусы каждого из подходов, и из этого сделать вывод по типу проекта.
XIB
что хорошо:
- Немедленное отображение результата — Я думаю, вы со мной согласитесь, что программировать UI проще, когда можно сразу же увидеть складывающуюся картинку.
- Подсвечивание атрибутов UI элемента — В IB есть замечательный Attributes Inspector, который подсвечивает нам основные поля для конфигурации. Удобно, тем более что в связке с первым пунктом дает понимание, как тот или иной атрибут влияет на View в целом 🤤
- Жесткий контроль за S в SOLID — в XIB можно максимально полно описать только один элемент, удобно при переиспользовании этого элемента в нескольких местах в проекте.
где болит:
- Это XML-файл, который даже при открытии без изменений в любой системе контроля версий может отобразиться как файл с изменениями. Это очень больно на проектах, в которых 2 и больше человек принимают участие.
- Невозможность изменять атрибуты элементов и констрейнты в рантайме — однажды скомпилировавшись в NIB, мы не можем поменять его значение без явного вмешательства в коде. Кстати поэтому динамически изменяемые вью не получится реализовывать через XIB.
- В списке атрибутов не подсвечены все возможные атрибуты, в частности layer, благодаря которому можно создавать тени, закругления, анимации. Про то, как решить эту проблему, я писал небольшую статью.
- Как ни странно, но третий минус в списке — это немасштабирование третьего в списке плюса: мы, к сожалению, имеем возможность полноценно создать только одну вью, вместо кластера вью, относящихся к одному экрану. Да, мы можем создать в IB несколько элементов, но использование функционала File’s Owner будет доступно только одному, что во многом ограничивает возможности других.
Storyboard
что хорошо:
Первые два пункта для XIB в равной степени применимы и для Storyboard, Поэтому продублируем:
- Подсвечивание атрибутов UI элемента
- Немедленное отображение результата
- Намного более широкие возможности конфигурации — Можно описать флоу навигации по экранам, переходы между экранами.
- Очень удобно переносить юзкейсы и сценарии использования, описанные в сервисах по типу Miro на сториборды.
где болит:
Аналогично, первые три пункта из XIB применимы и для Storyboad:
- Проблемы с CVS
- Невозможность изменять атрибуты элементов и констрейнты в рантайме
- В Attributes Inspector не подсвечены все возможные атрибуты
- Нельзя создавать отдельные UI элементы без отношения к ViewController — это неприятно, потому что затрудняет переиспользование элементов
- Data flow — хоть в Storyboards уже можно описывать навигацию и даже анимацию при переходах, дата флоу описать с его помощью не получится, а во многих случаях переход между экранами напрямую связан и с передачей данных.
Code
что хорошо:
- Время компиляции уменьшится за счет того, что компилятору не придется компилировать xml — вы выиграете во времени, что сэкономит приличное количество времени на больших проектах.
- UI станет по-настоящему reusable, причем его переиспользуемость может масштабироваться от лейбла до всего экрана.
- Конфигурация атрибутов UI элементов будет находиться в одном месте: для сложных UI-элементов, при создании их в IB, вам так или иначе придется писать код. Теперь задание атрибутов элементов будет только в коде. Круто же ?🕺
- Отсутствие конфликтов «по-причине-просто-так» один из ключевых плюсов.
- Кстати, если говорить про работу с системой контроля версий, то тут стоит еще сказать об облегчении ревью: для того, чтобы посмотреть реализацию UI не нужно переходить на ветку, и смотреть в IB — все заканчивается на этапе чтения кода.
- SwiftUI: предложенный Apple в конце 2019 подход к созданию приложений опирается на описание UI декларативным стилем программирования, быстро, легко и понятно. Там даже есть реал-тайм перевод из IB в код!
где болит:
- Очевидно, это отсутствие видимых изменений «в моменте», что увеличивает время создания UI элементов.
- Реально много кода: чтобы задать только одной вью 4 констрейнта, потребуется минимум 5 строчек. Если учесть, что у вью, помимо этого, есть и кастомизация атрибутов( в среднем 3–6 строчек), и при условии, что таких вью на экране будет много, это превращается в достаточно большой холст.
- При некорректной расстановке констрейнтов или их приоритетов, IB подсветит их красным и подскажет, каких констрейнтов не хватает. При кодинг подходе вы узнаете об этом только на этапе рантайма.
- Достаточно тяжеловесная работа с констрейнтами — для оптимизации необходимо придерживаться многих правил. Часто для этого прибегают к third-party библиотекам, которые уже реализовали это. В таком случае возникает зависимость от сторонних библиотек, что тоже не совсем хорошо. Напротив, IB вам сам расставит необходимые констрейнты, если вы его попросите, и проведет нужные оптимизации.
Фуух, вроде все описали. Осталось раскрыть основную цель статьи: что и когда использовать. Я бы предложил следующее разбиение:
- Если в команде разработчиков большое число человек, а задачи сильно связаны между собой, я считаю использование кода для UI наилучшим вариантом. Вы избежите проблем с конфликтами, вы всегда можете работать над одной UI задачей вместе, а проект будет компилироваться быстрее.
- При разработке проекта в команде до 3х человек или при грамотной декомпозиции задач можно комфортно использовать IB. Также я бы порекомендовал этот подход при сложной навигации в проекте — таким образом введение в проект новых людей будет происходить быстрее, да и в целом картинка перед глазами всегда приятна.
Учтите, что при выборе в пользу IB, вам все равно не избежать реализации некоторых моментов в коде. Также, даже если вы преимущественно работаете на storyboard, многие вещи можно вынести в xib, а затем переиспользовать в конфигурации экранов. Это уменьшит время компиляции и позволит поддерживать код в чистоте. Я попробовал оптимизировать подобный смешанный подход, результатом чего стала статья Make UI development easier in iOS
Всем удачи, пишите мне в twitter @PutkovD, если появились вопросы, буду рад на них ответить :)