Нативный backend-driven UI в iOS приложении на базе Editor.js
Как быстро интегрировать и нативно отрисовать контент статейного формата у себя в мобильном приложении, почти никак не нагрузив проект и всего с помощью нескольких строк кода? В этом материале я опишу наш способ решения такой задачи.
Материал может быть интересен любым мобильным продуктовым командам, где есть потребность в backend-driven верстке, а контент приложения - статьи, соглашения, документы, типовые карточки, списки и т.д.
Про инструмент
Инструмент, о котором пойдет речь - созданный нашей командой фреймворк Editor.js Kit. Он превращает JSON данные формата Editor.js в нативную мобильную верстку 👇
Предыстория
Пару лет назад наша команда столкнулась с задачей отрисовки в мобильном приложении новостных статей, пользовательских соглашений, экранов с описанием товара и других отформатированных массивов текста, чередующихся картинками, форматированными ссылками и списками. В общем, экранов статейного формата, как на TJ / VC. Контент должен был раздаваться бэкендом, а уже конкретный клиент (web / iOS / Android) форматирует и рендерит его в соответствии с представлениями о хорошем UX платформы и чувством прекрасного.
Задача, с одной стороны, тривиальная. Но, во-первых, экраны с таким контентом встречаются повсеместно почти во всех приложениях, и было бы хорошо придумать переиспользуемое универсальное решение. А во-вторых, вариант взять UITextView / WKWebView и скормить ему html верстку нам не подходит, поскольку данные должны быть легковесными, а верстка - нативной.
Было принято решение: пилим фреймворк.
Формат данных: Editor.js
При выборе формата для создания, хранения и передачи контента учитывали три фактора:
- Команда редакторов должна создавать статьи с форматированием в каком-то юзер-френдли веб-редакторе;
- Бэкенд API должен уметь принимать написанную статью с сохранением форматирования, хранить ее и раздавать ее всем клиентам на любые платформы в едином формате;
- Мобильный клиент должен принимать контент статьи, парсить его и рендерить нативно.
Думали не долго: наткнулись на Editor.js - тот самый редактор, про который на VC уже была статья. По словам авторов из команды CodeX, именно этот инструмент используется для написания статей на vc.ru, TJ и DTF.
Основная концепция — блочная структура и чистые данные в виде JSON на выходе. В отличие от большинства редакторов, где пользователь работает с текстом внутри одной редактируемой обертки, в Editor.js каждый структурный элемент статьи — блок — это отдельный редактируемый элемент. Блоки могут быть какие угодно: абзацы, заголовки, цитаты, списки, изображения, твиты, опросы и так далее.
Поддерживаемые блоки
Из коробки фреймворк поддерживает семь типов блоков: заголовок, параграф, изображение с подписью, ссылка, список нумерованный / буллет лист, разделитель и чистый html.
Парсинг контента
JSON данные могут отдаваться как с backend API, так и лежать локально в бандле или памяти смартфона - подготовка к его использованию будет одинакова и максимально проста в любом случае. Если кратко:
Подключение на экран
Для отрисовки экранов со скроллом мы почти всегда используем UICollectionView вместо UITableView в силу большей гибкости лейаута. Поэтому поддержку коллекции сделали в первую очередь. Любителей таблиц успокою - их поддержка легко добавляется адаптером по образцу коллекции.
Есть два основных сценария интеграции верстки себе на экран. Первый - когда ваш экран состоит только из Editor.js блоков. Это максимально просто делается через адаптер:
Второй сценарий - в случае, если вам надо встроить блоки в уже существующий экран с коллекцией, в любое его место. Для этого удобно использовать EJCollectionRenderer, который напрямую реализует методы dataSource и delegate коллекции и позволяет добавлять блоки в коллекцию в любом удобном порядке. Пример такой интеграции - в Readme на github.
Кастомизация стилей
В большинстве случаев в каждом проекте своя дизайн-система, то есть свои размеры шрифтов, отступы и цвета.
Рассмотрим базовую кастомизацию на примере заголовков:
Допустим, мы хотим изменить размер шрифта для каждого уровня заголовка, выровнять их по центру и значительно увеличить отступы сверху и снизу. За стиль заголовка отвечает протокол EJHeaderBlockStyle, который нужно реализовать:
Подключаем стиль:
В результате получаем задуманное форматирование без каких-либо изменений в коде вью или в JSON данных:
Кастомные блоки
Встроить в полотно скролла можно абсолютно любой блок, и для этого не понадобится писать слишком много кода.
Каждый JSON блок представляет собой два верхнеуровневых поля: type (тип блока) и data (JSON контент, который зависит от типа блока). Для примера придумаем и сделаем выноску - callout:
Первым делом создадим кастомный тип-перечисление для наших собственных блоков, сразу добавив туда callout:
Затем пропишем модель для поля data, важно проставить протоколы:
Следующим шагом пропишем стиль для нашей выноски, также реализуя EJBlockStyle:
И, конечно, верстка. В упрощенном виде, без деталей, реализация вью выглядит так:
Последний шаг: подключаем созданный блок к EJKit.
Готово! Смотрим на результат в виде светло-желтой выноски с шокированным котом в центре экрана:
Недостатки сегодня
- Поддерживается только отображение, контента, возможности редактирования блоков прямо с клавиатуры на смартфоне нет.
- Интерактив с контентом блоков отсутствует (кроме нажатия на гиперссылки и форматированные ссылки). Конечно, можно написать свой кастомный блок и прописать там всё, что душе угодно. Но никакой архитектуры на уровне фреймворка под поддержку интерактива не предусмотрено.
- Стили для семи поддерживаемых из коробки типов блоков не всеобъемлющи. У текста помимо цвета, шрифта и отступов есть, как минимум, междустрочный интервал, кернинг и т.п. Но опять-таки, ничто не мешает переопределить тот или иной блок или стиль под дизайн-систему вашего проекта.
Выводы
Editor.js Kit хорошо подойдет тем, у кого в мобильном продукте хотя бы на нескольких экранах нужно реализовать backend-driven верстку. При довольно малых временных затратах можно интегрировать к себе в приложение эстетичный нативный юзер интерфейс в соответствии с вашим дизайн-кодом, не захламив при этом проект сторонними зависимостями.
Наравне с no-code и low-code продуктами, наше решение призвано сократить время, которое команда тратит на дизайн тривиальных задач, а программист на написание boilerplate кода, что особенно важно для стартапов и командам на этапах создания MVP продукта.
Над фреймворком работала команда Upstarts.work
Авторы редактора Editor.js – CodeX Team