O Compose Multiplatform (CMP) evoluiu de forma significativa nos ultimos dois anos. Em 2026, a camada iOS saiu de alpha para beta estavel e ja sustenta aplicacoes em producao em empresas como Philips, Cash App e diversas startups brasileiras. Se voce acompanhou as novidades do Compose Multiplatform 1.10.6 ou ja usa CMP para desktop, este artigo mostra o que mudou para iOS e como levar seu projeto para producao com confianca.
Estado atual do Compose Multiplatform para iOS
A JetBrains declarou a camada iOS como Beta a partir da versao 1.7 e, desde entao, cada release trouxe ganhos de estabilidade e performance. O motor de renderizacao usa Skia via Skiko, o que significa que os composables sao desenhados pixel a pixel — sem depender de widgets nativos do UIKit.
Na pratica, isso traz duas consequencias:
- Consistencia visual entre Android e iOS sem esforco adicional.
- Necessidade de interop quando voce precisa de componentes nativos como mapas, cameras ou web views.
O ecossistema Kotlin Multiplatform fornece a base de compartilhamento de logica, enquanto o CMP cuida exclusivamente da camada de UI. Juntos, eles permitem compartilhar ate 90% do codigo entre plataformas.
Interop com UIKit usando UIKitView
Para componentes que exigem renderizacao nativa, o CMP oferece o composable UIKitView. Ele permite incorporar qualquer UIView dentro de uma arvore Compose:
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.interop.UIKitView
import platform.MapKit.MKMapView
@Composable
fun NativeMapView(modifier: Modifier = Modifier) {
UIKitView(
factory = { MKMapView() },
modifier = modifier,
update = { mapView ->
mapView.showsUserLocation = true
mapView.mapType = platform.MapKit.MKMapType.MKMapTypeStandard
}
)
}
O parametro factory cria a view nativa uma unica vez, enquanto update e chamado a cada recomposicao. Esse padrao e identico ao AndroidView no Jetpack Compose, o que facilita a transicao para quem ja desenvolve para Android.
Interop com SwiftUI
Alem do UIKit, o CMP suporta interop com SwiftUI por meio de UIKitViewController combinado com UIHostingController. Esse caminho e util quando voce quer reutilizar componentes SwiftUI existentes:
import androidx.compose.runtime.Composable
import androidx.compose.ui.interop.UIKitViewController
import platform.UIKit.UIViewController
@Composable
fun SwiftUIBridge(
factory: () -> UIViewController
) {
UIKitViewController(
factory = factory,
modifier = androidx.compose.ui.Modifier.fillMaxSize()
)
}
No lado Swift, voce cria o UIHostingController com a view desejada e passa como factory. Essa abordagem permite adotar CMP gradualmente, tela por tela, sem reescrever componentes SwiftUI que ja funcionam. Se voce esta avaliando a comparacao entre Kotlin e Swift para mobile, essa flexibilidade e um diferencial importante.
Expect/Actual para codigo especifico de plataforma
O mecanismo expect/actual do Kotlin Multiplatform e essencial para abstrair diferencas entre plataformas. Veja como definir um componente de status bar que se comporta de forma diferente em cada SO:
// commonMain
expect fun configurePlatformStatusBar(isDark: Boolean)
// androidMain
actual fun configurePlatformStatusBar(isDark: Boolean) {
val window = currentActivity.window
WindowCompat.getInsetsController(window, window.decorView)
.isAppearanceLightStatusBars = !isDark
}
// iosMain
actual fun configurePlatformStatusBar(isDark: Boolean) {
UIApplication.sharedApplication.setStatusBarStyle(
if (isDark) UIStatusBarStyleLightContent
else UIStatusBarStyleDarkContent,
animated = true
)
}
Esse padrao se aplica a qualquer funcionalidade que varie entre plataformas: notificacoes, biometria, armazenamento seguro e permissoes. O compilador K2 garante em tempo de compilacao que toda declaracao expect tenha uma implementacao actual correspondente.
Performance: CMP vs SwiftUI nativo
Um dos maiores questionamentos sobre CMP no iOS e a performance. Benchmarks recentes mostram que:
| Metrica | CMP (iOS) | SwiftUI nativo |
|---|---|---|
| Tempo de inicializacao | ~320ms | ~180ms |
| Scroll de lista (1000 itens) | 58-60 fps | 60 fps |
| Consumo de memoria (tela complexa) | ~45 MB | ~38 MB |
| Tamanho do binario (app minimo) | ~18 MB | ~8 MB |
O overhead de inicializacao vem do bootstrap do runtime Kotlin/Native e do Skia. Apos o start, a diferenca de performance e imperceptivel para o usuario. O tamanho do binario e maior por incluir o Skiko, mas tecnicas como strip de simbolos e link-time optimization reduzem esse impacto.
Para projetos onde a performance e critica, o profiling com Instruments da Apple funciona normalmente com binarios CMP. Alem disso, o suporte a Swift Package Manager no KMP simplifica a integracao com o toolchain iOS.
Estrategias de navegacao
A navegacao em projetos CMP para iOS segue dois caminhos principais:
- Navegacao compartilhada com bibliotecas como Voyager ou Decompose, onde toda a logica de navegacao vive no
commonMain. - Navegacao nativa usando
UINavigationControllerno iOS e Navigation Compose no Android, conectando via expect/actual.
A primeira abordagem maximiza o compartilhamento de codigo. A segunda oferece transicoes e gestos nativos (como o swipe-back do iOS). A escolha depende do quanto de UX nativa voce precisa preservar.
Para persistencia de dados local em ambas as plataformas, o Room com KMP e uma opcao madura que funciona tanto no Android quanto no iOS.
Quando escolher CMP para iOS
O Compose Multiplatform para iOS faz sentido quando:
- Voce ja tem uma equipe forte em Kotlin e nao quer manter dois codebases separados.
- A consistencia visual entre plataformas e mais importante que seguir pixel a pixel as guidelines do iOS.
- O projeto precisa de iteracao rapida e voce quer uma unica fonte de verdade para a UI.
Por outro lado, se o app exige integracao profunda com APIs exclusivas do iOS (HealthKit, ARKit, CarPlay), a camada nativa pode ser mais produtiva. A boa noticia e que o interop com UIKit e SwiftUI permite uma abordagem hibrida.
Desenvolvedores que vem de outras linguagens tambem encontram paralelos uteis. Em Go, o compartilhamento de codigo entre plataformas exige CGO e wrappers manuais. Em Python, frameworks como Kivy existem, mas nao oferecem a mesma integracao nativa. Ja em Rust, projetos como Slint avancam no cross-platform, mas a maturidade do ecossistema mobile ainda esta atras do CMP.
Conclusao
O Compose Multiplatform para iOS em 2026 e uma opcao viavel para producao. A combinacao de renderizacao Skia, interop flexivel com UIKit/SwiftUI e o mecanismo expect/actual cria um ambiente produtivo para equipes que querem maximizar o compartilhamento de codigo sem sacrificar a experiencia do usuario. Se voce ja usa KMP para logica de negocio, adicionar CMP para a camada de UI e o proximo passo natural.
Perguntas frequentes
O Compose Multiplatform para iOS esta pronto para producao?
Sim, em 2026 a camada iOS esta em Beta estavel e empresas como Philips e Cash App ja utilizam em producao. A JetBrains oferece suporte ativo e cada release traz melhorias de estabilidade e performance.
Qual a diferenca de performance entre CMP e SwiftUI nativo?
Apos a inicializacao, a diferenca e minima. O scroll de listas complexas roda a 58-60 fps em CMP contra 60 fps em SwiftUI. O maior impacto esta no tamanho do binario (~18 MB vs ~8 MB) e no tempo de cold start (~320ms vs ~180ms).
Posso usar componentes nativos do iOS dentro do Compose Multiplatform?
Sim, o composable UIKitView permite incorporar qualquer UIView nativa dentro da arvore Compose. Para componentes SwiftUI, voce pode usar UIKitViewController com UIHostingController como ponte.
Preciso reescrever todo o app para usar CMP no iOS?
Nao. O CMP suporta adocao gradual. Voce pode comecar com uma unica tela compartilhada e manter o restante do app em SwiftUI ou UIKit, expandindo o uso conforme ganhar confianca na ferramenta.