В феврале вышел Compose Multiplatform 1.6 - первая версия, в которой iOS-таргет JetBrains назвала Stable. К июлю у нас два продакшн-проекта на CMP с поддержкой обеих платформ. Делимся, как это устроено и где всё ещё тонко.
Какая часть кода реально шарится
На обоих проектах структура примерно одинаковая: shared слой содержит модели данных, бизнес-логику, репозитории, ViewModel-аналоги, и большую часть UI. Платформенно остаются глубокие интеграции (камера, push, биометрия, in-app purchases) и пара экранов с очень платформенным UX.
Метрика по строкам: на проекте поменьше - 78% общий код, 22% платформенный. На проекте побольше (с тяжёлой камерой и медиа) - 64% общий, 36% платформенный.
Что приятно удивило
- Compose-рендеринг на iOS работает плавно - на тестовых устройствах от iPhone 11 и выше держим 60fps на сложных списках.
- Hot reload на iOS наконец работает без шаманства.
- Тёмная тема, динамическая типографика, локализации - настраивается из Compose, без двух наборов ресурсов.
- Размер итогового бинарника на iOS вырос всего на ~6 МБ относительно нативной альтернативы.
Что всё ещё больно
Системные UI-компоненты
Текстовое поле на iOS из коробки не имеет того же UX, что нативный UITextField (выделение, контекстное меню, smart-quote). Для большинства экранов это незаметно, для редактора длинных текстов - пришлось делать UIViewRepresentable-обёртку.
Accessibility
VoiceOver работает, но не так гладко, как с нативным SwiftUI. Сложные кастомные компоненты пришлось доразмечать вручную. Это решаемо, но требует отдельного инженера на проверку.
Сторонние библиотеки
Множество Android-библиотек используют Context, View и другие платформенные классы - на iOS они не работают. Приходится либо искать KMP-аналоги, либо писать expect/actual обёртки.
Когда мы рекомендуем CMP
- Команда уже сильна в Kotlin/Android, найм Swift-инженеров затруднён.
- Бренд-консистентный UI важнее платформенного.
- Бизнес-логика сложная и её жалко дублировать.
- Не нужны глубокие интеграции с системными API первого дня.
Когда не рекомендуем
- Команда сильна в Swift и React, Kotlin не знает.
- Продукт сильно платформенный (виджеты, Live Activities, ActivityKit, Material You).
- Игра, AR, тяжёлое медиа - здесь натив или Unity.
- Маленький MVP, на котором не успеете окупить настройку KMP-инфраструктуры.