Всем привет, меня зовут Фарид Хусаинов, я тим-лид команды мобильной разработки Банки.ру. Мы делаем iOS-приложения компании Банки.ру, а именно – наше основное приложение и приложение, посвященное страхованию.

Два с половиной года назад мы приняли решение перевести наше мобильное приложение на SwiftUI. На тот момент это была смелая и рискованная идея, так как SwiftUI был новой технологией. Маленькое комьюнити, много багов и нехватка опытных разработчиков, работающих на этой платформе, делали этот шаг непростым.

Эту статью хотелось бы адресовать разработчикам, интересующимся SwiftUI, а также тим-лидам и представителям бизнеса. Она в меньшей степени посвящена разработке, а в большей – опыту взаимодействия с новой технологией в продакшене. Мы подробно рассмотрим, почему мы выбрали SwiftUI и как справлялись с различными вызовами на этом пути.

Что такое SwiftUI

SwiftUI - это фреймворк для декларативной вёрстки пользовательского интерфейса приложений в экосистеме Apple на языке Swift.

Декларативный подход на SwiftUI выглядит вот так:

На принтскрине один файл с достаточно простым кодом. Все легко можно прочитать и понять. Здесь мы видим, что нас попросили сделать столбик из каких-то элементов, отступ между которыми 50. Сверху в этом столбике находится текст, потом идёт кнопочка, которая при нажатии меняет это приветствие, у неё текстовая подпись и под кнопкой пустое пространство. И все это сдвинуто от верха экрана на 100 пикселей. Все понятно.

Почему мы выбрали Swift UI и как дошли до жизни такой: история SwiftUI.

Первый SwfitUI Apple выпустили вместе с iOS 13 в 2019 году. И на тот момент технология была довольно сырой. Я бы сказал, что даже нетипично сырой для Apple: было много багов. Удивляло также то, что в SwiftUI отсутствовали некоторые элементы, которые были в легаси фреймворке UIKit. К примеру, многострочное текстовое поле.

Но стоит отметить, что Apple сразу выпустили хорошую документацию. И самое главное, что в коробке с этим фреймворком пришёл ещё один фреймворк - Combine. Это реализация реактивного фреймворка, полностью написанного Apple и полностью встроенного в SwfitUI. То есть вся динамика и все, что происходит в SwfitUI, работает на Combine. И этот Combine оказался очень стабильным и сразу хорошо задокументированным. Естественно, его можно использовать отдельно, что мы и делали: в частности, у нас на нем работает сетевой слой.

В iOS 14 в 2020 году Apple исправили некоторые баги и добавили новые возможности. Также появилось больше документации: учебники, интерактивные уроки и так далее. Но некоторые баги по-прежнему сохранялись. И как раз на этом этапе мы выпустили приложение Banki.ru и решили, что все новые фичи мы пишем только на SwiftUI. 

У нас получилась такая ситуация, что часть, написанная на аутсорсе, оставалась на UIKit, а то, что мы писали сами, создавалось уже на SwiftUI. На тот момент шаг был довольно рискованным, но мы верили, что Apple будет развивать технологию, и непреодолимых препятствий в будущем это не создаст. Спойлер: так и случилось.

Как мы и предполагали, в версии iOS 15 и 16 багов стало заметно меньше, добавились дополнительные возможности, реализовались новые компоненты. 

К тому моменту SwfitUI уже мог называться stable-версией.

Когда начинать использовать новые технологии

Наш опыт показал, что новые инструменты стоит внедрять как можно раньше. Конечно, использование новых инструментов и подходов в продакшене - это всегда риски и поиск компромиссов. Многие разработчики и команды не готовы идти на это. Но мы видели потенциал SwfitUI с самого начала, верили, что за ним будущее, и хотели оказаться «на гребне волны». И наш подход принес результаты.

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

Например, даже SwiftUI в свое время вызывал сомнения. Многие разработчики не верили в его потенциал и избегали его использования. Некоторые приняли этот язык только с четвертой версии. Так было и с многими другими технологиями, которые теперь являются стандартами отрасли.

Взаимодействие с бизнесом

При внедрении новых инструментов в рабочие процессы необходимо уделить внимание взаимодействию с бизнесом. Бизнес-сторона должна осознавать, что, хотя новые технологии могут приносить значительные выгоды в будущем, в настоящем приходится идти на некоторые компромиссы. Это вполне нормальная часть процесса.

Рассмотрим пример: в ранних версиях технологии не всегда можно в точности воплотить все элементы интерфейса, как они изображены на дизайн-макете. В таких случаях ключевую роль играет отличная коммуникация между разработчиками, дизайнерами, продуктовыми менеджерами и другими участниками команды. Необходимо совместно искать оптимальные альтернативные решения и адаптировать технологию к конкретным требованиям и ограничениям проекта. Это позволяет успешно интегрировать новые инструменты и максимизировать их потенциал, несмотря на временные компромиссы.

Плюсы SwiftUI

Переводя проект на SwiftUI, мы ожидали получить следующие преимущества:

Понятный код

SwiftUI не требует написания множеств строк кода. При этом весь код находится в одном месте. Все отступы называются отступами, а пустые пространства - пустыми пространствами. Это позволяет нам без проблем решать мерж-конфликты и проводить код-ревью.

Превью

Вместе со SwiftUI появились превьюшки. Это такая картинка, которую наш редактор кода может показать отдельно. То есть мы можем нажать на конкретную кнопочку и увидеть нашу вьюшку с какими-то нашими тестовыми данными, которые мы

захотели в данном случае увидеть. Это позволяет отслеживать все наши изменения прямо в реальном времени. Ничего не надо компилировать, что делает жизнь разработчика гораздо проще.

Отсутствие сторонних фреймворков

Также вместе с SwiftUI из коробки идет Combine. Поэтому нам не приходится добавлять сторонние фреймворки. Таким образом, мы повышаем безопасность нашей кодовой базы.

Хочется подчеркнуть, что особенность этого подхода — его декларативность. Работая таким способом, стоит понимать, что мы описываем не действия, а взаимосвязь между определенными сущностями: между нашими данными и тем местом, в котором они отображаются. Это может потребовать изменения нашего способа мышления и привести к более абстрактному пониманию процесса.

Проблемы SwfitUI

Конечно, работа с любой новой технологией в продакшене подразумевает некоторые проблемы. Расскажем, с чем мы столкнулись на нашем тернистом пути.

Баги

Баги в Apple-фреймворках действительно могут быть неприятными, так как компания не раскрывает свой исходный код, и исправить проблему могут только сами разработчики Apple. Это требует активного уведомления и убеждения Apple в необходимости исправления. Обычно исправления багов доступны только в следующей версии iOS, что может занять достаточно много времени, порой год или даже больше.

Необходимость «костылить»

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

Показательный пример необходимости костылить — это «ромашка» на экране ниже. Этот элемент пользователь видит на долю секунды, когда тянет экран вниз, чтобы перезагрузить. Но именно этот незначительный, казалось бы, элемент принес нам много головной боли.

Мы переделывали его на протяжении всех обновлений IOS. 

В iOS 13 не было нативного компонента для этой ромашки, мы делали свою эмуляцию. 

В iOS 14 мы смогли через обходные пути кое-где включить нативную реализацию. 

В IOS 15 нам представили нативный элемент, но оказалось, что он не работает в некоторых условиях. Пришлось искать условия, где он не работает, и использовать на них нашу реализацию. А для условий, где он работает, мы использовали нативный. Таким образом, мы выстроили огромный многоэтажный костыль.


Зоопарк устройств для тестирования

И каждый раз при обновлении операционной системы для тестирования начинается горячая пора. Нужно проверить все приложение, чтобы не возникло никаких сюрпризов.

При этом в идеальной картине мира нам не достаточно держать пару устройств на последней версии iOS и этим довольствоваться. Все-таки желательно иметь весь стек, начиная с устройств с iOS 13, потому что в каждой версии операционной системы есть свои особенности, и нам их необходимо учитывать. Но это слишком энергозатратно, поэтому оптимальный подход - уделять максимальное внимание именно последним версиям. Тем более что большинство пользователей iOS обновляются оперативно. А на более старых версиях полную идентичность и функциональность приложения мы гарантировать, к сожалению, не можем.

Запасной вариант 

После изучения недостатков и багов SwiftUI мы пришли к выводу, что все эти проблемы решаемы, хотя и требуют творческого подхода. Далее я расскажу о некоторых методах, которые мы применяли, чтобы справиться с этими вызовами в нашей работе.

Возможности решения багов оказались довольно обширными, потому что, по сути, SwiftUI — это всего лишь надстройка над UIKit. Зная это, через код можно докопаться до исходных элементов.


Кроме того, SwiftUI позволяет создавать UIViewRepresentable-оболочки над компонентами из UIKit, если они отсутствуют в SwiftUI. Эти оболочки позволяют использовать UIKit-компоненты в вашем интерфейсе так, как если бы они были обычными компонентами SwiftUI. В частности, в большинстве мест приложения текстовые поля под капотом — UIKit-компоненты, завёрнутые в SwiftUI-обертку – ввиду того, что их SwiftUI-аналог не обладает всеми фичами, необходимыми нам.

Третий вариант — это оставлять целые экраны на UIKit, а новые - писать на SwiftUI. Например, у нас в одном приложении с успехом существует главный экран на UIKit. Однако, почти все остальные экраны уже мигрировали на SwiftUI, и это происходило часто незаметно. При этом иногда даже наши продакт-менеджеры не знали, что мы в прошедшем спринте переписали целый экран на SwiftUI.

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

Порог входа, поиск разработчиков

Переход на SwiftUI поставил перед нами проблему поиска разработчиков. Очевидно, что с появлением SwiftUI не все Swift-разработчики устремились его осваивать, ведь на тот момент компании его мало использовали, мотивации изучать его не было.

Но важно отметить, что SwiftUI — это достаточно простая технология, она обладает большим объемом документации и учебников, поэтому осваивается буквально за неделю. То есть если к нам приходит разработчик, который подходит нам по всем параметрам, но не знает SwiftUI, то через недельку он уже будет пилить кнопки.

Самое главное требование к кандидату – понимание реактивного подхода к интерфейсу, при котором изменения данных автоматически отображаются в интерфейсе без необходимости явного управления.

Поэтому достаточно, чтобы разработчик был знаком с каким-либо реактивным фреймворком, поскольку весь SwiftUI работает на основе Combine. Фактически не важно, с каким реактивным фреймворком кандидат знаком, так как подходы к реализации реактивности остаются схожими как SwiftUI, так и на других языках, таких как Java. Поэтому, если у вас есть опыт с RxSwift или ReactiveCocoa, освоение Combine будет относительно простым. Возможно, даже не потребуется полное освоение, так как можно использовать справочные материалы для перевода знаний о том, какая концепция в Swift соответствует той же концепции в Combine.

Рынок 

И конечно, в связи с этим можно задаться вопросом: как обстоят дела на рынке, есть ли нужные нам кандидаты?

Когда мы только решили переходить на SwiftUI, всех кандидатов на нашу вакансию можно было поделить на три условные группы:

  • Люди, которые ни за что не были согласны писать на SwiftUI. Они считали использование SwiftUI на продакшене безумием. Таких кандидатов было мало, они отказывались прямо на собеседовании. 

  • Скептически настроенные разработчики. Я сам был из таких, когда приходил на проект, но меня уговорили попробовать.

  • Группа энтузиастов. Они тоже считали, что технология не готова к продакшену, но уже интересовались и хотели попробовать этим позаниматься.

С течением времени ситуация сильно поменялась и сейчас уже никто с ходу не отказывается узнав, что у нас SwiftUI в продакшене.

Скептиков тоже как-то поубавилось. В основном, кандидаты готовы попробовать с этим поработать, интересуются, как технология у нас применяется.

Появилась ещё интересная категория — это кандидаты, которые прямо на входе говорят, что принципиально хотят работать только со SwiftUI. 

Вот такие перемены мы наблюдаем на рынке в последнее время.

Выводы: стоило ли оно того

Какие выводы мы сделали после 2,5 лет со SwiftUI в продакшене:

Если не мы, то кто?

Начав использовать SwiftUI, мы стали энтузиастами новых технологий. Как показала наша практика, это было верным решением. Ведь чем раньше начать использовать новый подход в проекте, тем более целостным и единообразным он будет. И в будущем у вас не возникнет желания переписывать тонны кода с UIKit на SwiftUI. А новым разработчикам будет легче приступать к работе и вливаться в проект.

Всегда есть пути к отступлению

Мы с самого начала считали, что нерешаемых проблем у нас не будет, и мы всегда найдем решение. Какие-то пути к отступлению найдутся: мы можем использовать legacy-подходы или искать другие варианты. А если опций совсем не остается, то можно договориться с коллегами и нарисовать экран немного иначе.

Взаимодействие с бизнесом

Это вывод следует из предыдущего. Внедряя новый инструмент в работу, нужно обязательно подготовиться на уровне взаимодействия с бизнесом. Бизнес должен быть готов к тому, что некоторые элементы дизайна на данной версии технологии могут быть реализованы иначе. То есть открыт к диалогу с разработчиками.

Сокращение времени на верстку

Если говорить о выгоде, то можно утверждать, что да, мы получили профит. Время, затрачиваемое на верстку, значительно сократилось.

Проще архитектура

В SwiftUI все делится на два слоя: на визуальный слой и на данные. Они довольно прозрачно связываются. Таким образом, структура проекта становится более логичной. Соответственно, не нужно писать какие-то вещи, которые будут это все связывать, и таким образом упрощается архитектура приложения. Оно становится более целостным, без использования сторонних фреймворков

А как же баги?

От багов никуда не деться, с ними приходится постоянно справляться.

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

Поддержка Apple

Но при этом явно видно, что подход активно продвигается Apple. В частности, они сами начали писать на SwiftUI некоторые нативные приложения, которые мы получаем вместе с телефоном из коробочки. К примеру, калькулятор, виджеты, интерфейс для часов написаны на SwiftUI

Очевидно, что Apple будут продвигать дальше эту технологию. 

И из этого ещё вытекает то, что они продвигают SwiftUI как единый фреймворк для всех вариантов своей платформы. И когда мы пишем интерфейс, то можем ожидать, что он будет одинаково работать на телефонах, на часах, на телевизорах и на десктопах. Это значит, что приложение Banki.ru мы чисто теоретически можем запустить на маке.

Конечно, мы рисковали, начиная работу с SwiftUI. Многие разработчики сомневались в его перспективах. Были проблемы и баги. Но все оказалось решаемым.

Мы изучали ошибки, создавали свои методы работы. Мы освоили реактивный подход с использованием Combine, а также выстроили хорошую коммуникацию с коллегами на случай поиска альтернативных решений.

Спустя два с половиной года наше приложение на SwiftUI успешно функционирует и продолжает развиваться. Оно стало более удобным в поддержке. В целом, можно сказать, что переход на SwiftUI оказался успешным для нашей компании. 

Комментарии (9)


  1. spiceginger
    25.10.2023 15:40

    Просто поныть раз нет комментариев. Про переписанные на SwiftUI стандартные приложения. В OsX там так еще хуже.
    https://twitter.com/EKazaev/status/1704532389609796081 https://twitter.com/justinxinliu/status/1715437703989191138


  1. varton86
    25.10.2023 15:40

    В копилку xCode и IOS добавился Swift UI.


  1. dprotopopov
    25.10.2023 15:40
    -3

    То есть пофиг что аппл пофиг рассия?

    Есть ли здесь и сейчас смысл вкладываться в изучение-внедрение технологий Apple? (лично у меня сомнения)


  1. Rusrst
    25.10.2023 15:40

    Я не iOS разработчик, но плотно работаю с compose в Android. И если кастомные элементы в swift ui делать так же просто, то не понимаю страданий по ромашке, задача на 1-2 дня свою написать. А если картинку просто крутить, то и того быстрее.

    И если сложность равна таковой в compose, то я бы не сказал что за неделю все понять получится...


    1. lorwe
      25.10.2023 15:40

      Саму "ромашку" в SwiftUI сделать не сложно, однако нативная довольно плотно интегрируется со своим контейнером и влияет на его поведение: отступы, панель навигации...
      При условии понимания общей концепции и наличии достаточного опыта за пределами SwiftUI, через неделю человек уже может верстать простые интерфейсы и решать продуктовые задачи.


  1. debug45
    25.10.2023 15:40

    В этом году Apple внезапно убила Combine и выкатила ему на замену новый фрейворк — Observation. Как быть с ним?


    1. lorwe
      25.10.2023 15:40

      Не сказал бы, что Apple "убила" Combine или же Observation полностью его заменяет. Хотя бы потому что Observation доступен для iOS 17, а значит в продакшене его можно будет применить довольно не скоро, т.к. многие компании требуют поддержки старых версий операционной системы.


  1. Gargo
    25.10.2023 15:40

    Основная проблема SwiftUI не упомянута - Preview иногда крашится даже от простого "Hello World". Как вы поступаете в таких случаях?

    И да, SwiftUI до сих пор нестабильный.


    1. lorwe
      25.10.2023 15:40

      Корректно ли говорить, что это – проблема SwiftUI? Скорее, это – проблема Xcode. Кстати не единственная. Там вообще много интересного творится. Ощущение, что проблемы начинаются, когда Xcode пытается интегрироваться с продуктами других команд внутри самой Apple, не говоря уж о том, что сама IDE, так скажем, не идеальна.

      Preview крашится. Факт. Но это лучше, чем ничего.