85. UITabbarController + SwiftUI
Недавно делал необычную задачу в сжатые сроки. У меня был SwiftUI-таббар, который нужно было встроить в UITabbarController. В этой статье покажу как я решил эту задачу.
Демо результата
Внешний вид экранов и вьюхи для таббара тут не так важны как интеграция UIKit и SwiftUI.
Краткое описание решения
Поскольку времени на задачу было немного, я решил попробовать самое быстрое на мой взгляд решение: подставить кастомную SwiftUI-вьюху поверх стандартного таббара, а стандартный в свою очередь скрыть по максимуму:
1. Делаем свой сабкласс для UITabbarController
2. Делаем свой сабкласс для UITabBar и задаем в нем нужную нам высоту таббара в методе sizeThatFits
3. Подключаем в инициализаторе для UITabbarController наш кастомный UITabbar: object_setClass(self.tabBar, CustomTabBar.self)
4. В методе viewDidLoad настраиваем appearance для таббара, что заслуживает отдельного внимания, ведь нам нужно целиком скрыть все тексты и иконки из стандартного таббара. Вкратце: настриваем параметры standardAppearance и scrollEdgeAppearance
5. Там же внутри viewDidLoad подключаем на констрейнтах SwiftUI-вьюху через UIHostingController и не забываем последнему задать прозрачный цвет для вьюхи
6. Нажатия на “табы” в SwiftUI-вьюхе передаем через “вьюмодель” (ObservableObject) наружу в замыкании. Без ObservableObject обмен данными не работает между UIKit и SwiftUI.
Шаги 2 и 3 опциональные, нам по дизайну нужна была кастомная высота.
Нюансы
- Пока не решена задача скрытия таббара - стандартный скрывается исправно, а вот SwiftUI-вьюха остается на экране
- Кастомная высота для таббара задается ну очень костыльно на мой взгляд, другого варианта для UIKit не нашел на скорую руку
- Все решение выглядит костыльно (в коде), зато работает классно и можно реализовать за пару дней с нуля
Заключение
UIKit вполне может работать со SwiftUI, и даже такие нетривиальные сценарии работают отлично, главное знать как подружить эти два инструмента.
Код для этой статьи можно посмотреть тут.