Kotlin Multiplatform en 2026: ¿está por fin listo para desarrolladores iOS?
Llevo trabajando en desarrollo móvil desde 2014 y, durante estos años, he pasado por diferentes aproximaciones al eterno problema de compartir código entre iOS y Android.
He trabajado con Xamarin, posteriormente con .NET para iOS y Android, con MAUI y, por supuesto, con desarrollo nativo. Más recientemente he empezado a trabajar con Kotlin Multiplatform (KMP).
Y KMP plantea el problema de una forma que me resulta especialmente interesante.
Porque, a diferencia de otras soluciones multiplataforma, utilizar Kotlin Multiplatform no significa necesariamente decidir que toda nuestra aplicación debe ser multiplataforma.
Podemos compartir aquello que tiene sentido compartir y mantener completamente nativo aquello que tiene sentido que siga siendo nativo.
Para un desarrollador iOS, esa diferencia es importante.
Así que la pregunta que quiero intentar responder en este artículo no es qué es Kotlin Multiplatform ni cómo crear nuestro primer proyecto.
La pregunta es otra:
En 2026, ¿utilizaría Kotlin Multiplatform en una aplicación iOS real?
La respuesta corta es sí.
La respuesta larga es bastante más interesante.
KMP no significa abandonar Swift
Creo que esta es una de las primeras ideas que conviene aclarar.
Cuando hablamos de desarrollo multiplataforma solemos pensar inmediatamente en compartir toda la aplicación:
- lógica de negocio,
- acceso a datos,
- navegación,
- interfaz de usuario.
Pero Kotlin Multiplatform no nos obliga a hacerlo así.
Podemos utilizar Kotlin para implementar una capa compartida entre Android e iOS y seguir desarrollando nuestra aplicación iOS utilizando Swift, SwiftUI o incluso UIKit.
Una arquitectura bastante razonable podría ser:
┌──────────────────────┐
│ Shared KMP │
│ │
│ Networking │
│ Repositories │
│ Business logic │
│ Models │
│ Persistence │
└──────────┬───────────┘
│
┌───────────┴───────────┐
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ Android │ │ iOS │
│ │ │ │
│ Kotlin / │ │ Swift / │
│ Compose │ │ SwiftUI │
└─────────────┘ └─────────────┘
Desde el punto de vista de iOS, shared se convierte básicamente en una dependencia más de nuestra aplicación.
Y esto cambia bastante la conversación.
No estamos intentando sustituir iOS.
Estamos intentando evitar implementar dos veces aquello que realmente no necesita tener dos implementaciones.
¿Qué compartiría?
Aquí es donde creo que KMP empieza a tener mucho sentido.
Imaginemos una aplicación que consume una API.
Probablemente tengamos:
- DTOs,
- llamadas HTTP,
- serialización,
- repositorios,
- caché,
- validaciones,
- reglas de negocio,
- casos de uso.
Tradicionalmente acabaríamos implementando buena parte de esa lógica dos veces.
Una implementación en Kotlin para Android y otra en Swift para iOS.
Y mantener ambas implementaciones sincronizadas no siempre es trivial.
Una regla aparentemente sencilla como:
Si el usuario está autenticado,
tiene permisos X,
el elemento está activo
y además cumple la condición Y,
mostrar la acción Z.
termina existiendo dos veces.
Y tarde o temprano una de las dos implementaciones cambia.
Con KMP esa lógica puede vivir en un único lugar.
En cambio, personalmente no empezaría compartiendo la interfaz.
Compose Multiplatform permite hacerlo y puede ser una opción perfectamente válida dependiendo del proyecto, pero una de las cosas que más me interesan de KMP es precisamente no estar obligado a compartirla.
En iOS puedo seguir utilizando SwiftUI, UIKit, MapKit, WKWebView o cualquier API específica de Apple cuando sea la solución adecuada.
El verdadero problema para iOS: Kotlin tiene que llegar hasta Swift
Hasta aquí todo suena bastante bien.
Pero hay una frontera que cualquier proyecto KMP con iOS termina encontrando:
Kotlin → Swift
Y esta frontera es probablemente donde más se nota que estamos trabajando con dos ecosistemas diferentes.
Actualmente, gran parte de la interoperabilidad de Kotlin/Native con Swift sigue pasando por la interoperabilidad con Objective-C.
Eso funciona.
Pero que algo funcione no significa necesariamente que resulte natural desde Swift.
Podemos encontrarnos diferencias en:
- nombres generados,
- nullability,
- genéricos,
- enums y sealed classes,
- excepciones,
- colecciones,
suspend,Flow.
Un API perfectamente idiomático desde Kotlin puede convertirse en algo bastante menos agradable cuando lo consumimos desde Swift.
Por eso una de las lecciones que considero importantes al trabajar con KMP es esta:
La API del módulo compartido también debe diseñarse pensando en iOS.
No basta con escribir Kotlin y esperar que Swift se adapte.
Coroutines: cuando Kotlin y Swift hablan idiomas distintos
Un ejemplo especialmente interesante son las coroutines.
En Kotlin podríamos tener algo tan normal como:
suspend fun getUser(): User
o:
val state: StateFlow<ScreenState>
Desde Kotlin estas APIs son completamente naturales.
Desde Swift la historia tradicionalmente ha sido bastante menos elegante.
Swift tiene su propio modelo de concurrencia:
async / await
y sus propias formas de representar secuencias asíncronas.
Kotlin tiene:
suspend
Flow
StateFlow
SharedFlow
El problema no es que ninguno de los dos modelos sea malo.
El problema es hacerlos hablar entre ellos.
En proyectos reales esto suele llevar a introducir una pequeña capa de adaptación o herramientas como KMP-NativeCoroutines, que permiten presentar estas APIs de una forma mucho más natural desde Swift.
Por ejemplo, queremos que conceptualmente algo como:
suspend fun loadProfile(): Profile
termine pudiéndose consumir desde iOS aproximadamente como:
let profile = try await repository.loadProfile()
y no obligar al desarrollador iOS a conocer los detalles internos de Kotlin/Native.
Cuanto más pequeña y limpia sea esta frontera, mejor será la experiencia del equipo iOS.
Swift Export puede cambiar bastante esta situación
Y aquí llegamos a una de las partes más interesantes de KMP en 2026.
JetBrains está desarrollando Swift Export, cuyo objetivo es permitir exportar APIs Kotlin directamente a Swift de una manera mucho más natural, eliminando muchas de las limitaciones heredadas del puente con Objective-C.
En el momento de escribir este artículo, Swift Export sigue estando en Alpha, aunque JetBrains tiene en su roadmap llevarlo a Beta.
Entre otras cosas, permite conservar mejor conceptos como:
- módulos,
- packages,
- type aliases,
- nullability.
Pero Kotlin 2.4.20 ha introducido además mejoras particularmente interesantes.
Una de ellas es el soporte para sealed classes.
Imaginemos:
sealed interface Result {
data class Success(val value: String) : Result
data class Error(val message: String) : Result
}
Una jerarquía como esta puede representarse ahora mediante Swift Export de una forma que permite realizar un switch exhaustivo desde Swift.
Eso es importante.
No solamente porque el código quede más bonito, sino porque el compilador puede avisarnos cuando añadimos un nuevo caso en Kotlin que todavía no estamos tratando en iOS.
También se ha añadido soporte para cross-language inheritance.
Esto permite definir un contrato en Kotlin y proporcionar determinadas implementaciones desde Swift.
Es especialmente útil cuando nuestra capa compartida necesita algo que pertenece claramente al mundo Apple.
Por ejemplo:
Shared Kotlin
│
│ necesita CryptoProvider
▼
Swift implementation
│
▼
CryptoKit
Kotlin conoce el contrato.
Swift proporciona la implementación utilizando APIs nativas de Apple.
Para mí, esta dirección es bastante más interesante que intentar abstraer absolutamente todo detrás de implementaciones multiplataforma.
La integración con Xcode también está mejorando
Otro punto históricamente incómodo de KMP ha sido la integración del artefacto generado con el proyecto iOS.
Kotlin/Native genera frameworks que podemos consumir desde nuestra aplicación.
Dependiendo del proyecto podemos utilizar integración directa, CocoaPods o distribuir un XCFramework mediante Swift Package Manager.
Kotlin 2.4.20 mejora también este último escenario.
Al generar determinados XCFrameworks que utilizan dependencias SwiftPM, Gradle puede generar ahora automáticamente el Package.swift necesario para distribuirlos.
Parece una mejora pequeña.
Pero este tipo de mejoras son precisamente las que hacen que KMP empiece a sentirse menos como algo añadido alrededor de Xcode y más como una pieza normal de una arquitectura móvil.
Pero todavía hay fricción
Llegados a este punto podría parecer que todo está solucionado.
No lo está.
Y creo que es importante decirlo.
Kotlin Multiplatform es estable y puede utilizarse perfectamente en producción, pero eso no significa que toda la experiencia de desarrollo para iOS tenga el mismo nivel de madurez que trabajar exclusivamente con Swift.
Hay varias áreas donde todavía existe fricción.
Build times
Kotlin/Native ha tenido históricamente problemas con los tiempos de compilación.
JetBrains continúa trabajando activamente en este punto.
Kotlin 2.4.20, por ejemplo, incluye mejoras en la compilación incremental de artefactos klib, que actualmente está en Beta.
Es una mejora importante, pero el simple hecho de que siga siendo un área activa de optimización nos dice que todavía existe margen de mejora.
Debugging
Cuando todo nuestro código está en Swift, Xcode entiende perfectamente nuestro mundo.
Cuando una parte de la ejecución entra en Kotlin, la experiencia deja de ser tan transparente.
De hecho, la integración del debugger de Kotlin/Native con Xcode sigue figurando actualmente entre los objetivos del roadmap de Kotlin.
Swift Export todavía no es estable
Probablemente sea una de las piezas que más puede mejorar la experiencia de KMP para desarrolladores iOS.
Pero hoy sigue estando en Alpha.
Eso significa que yo no diseñaría una arquitectura crítica asumiendo que todas sus APIs actuales permanecerán exactamente igual.
Hay que diferenciar claramente dos cosas:
Kotlin Multiplatform es estable.
Swift Export todavía no lo es.
Y ambas afirmaciones pueden ser ciertas al mismo tiempo.
¿Y Compose Multiplatform?
Hasta ahora prácticamente no he hablado de Compose.
Es deliberado.
Kotlin Multiplatform y Compose Multiplatform no son lo mismo.
KMP nos permite compartir código.
Compose Multiplatform nos permite además compartir interfaz.
Podemos construir una aplicación donde:
Business logic → KMP
Android UI → Compose
iOS UI → SwiftUI
pero también:
Business logic → KMP
UI → Compose Multiplatform
o incluso utilizar una combinación de ambas estrategias.
Personalmente creo que esta separación es una de las fortalezas de KMP.
No necesitamos tomar una decisión absoluta.
Podemos empezar compartiendo una parte pequeña del dominio y ampliar progresivamente la superficie compartida si realmente aporta valor.
Lo que cambia respecto a Xamarin o MAUI
Viniendo de Xamarin y del ecosistema .NET, esta diferencia me resulta especialmente interesante.
Durante años he trabajado con tecnologías cuyo objetivo era permitir desarrollar aplicaciones para varias plataformas utilizando fundamentalmente un mismo ecosistema.
KMP parte de una filosofía algo distinta.
No intenta necesariamente reemplazar las plataformas.
Se introduce entre ellas.
Android puede seguir siendo Android.
iOS puede seguir siendo iOS.
Y existe una capa compartida donde colocamos aquello que realmente tiene sentido implementar una única vez.
Esto también cambia el papel del desarrollador iOS.
No desaparece Swift.
No desaparece Xcode.
No desaparecen UIKit o SwiftUI.
El desarrollador iOS sigue siendo responsable de que la aplicación se comporte como una aplicación iOS.
Simplemente deja de tener que implementar necesariamente toda la lógica que existe por debajo.
Entonces, ¿está KMP listo para iOS en 2026?
Creo que aquí hay que separar dos preguntas.
¿Está listo para producción?
Sí.
Kotlin Multiplatform está oficialmente considerado estable desde Kotlin 1.9.20 y lleva años utilizándose en aplicaciones reales.
No considero que utilizar KMP en 2026 sea apostar por una tecnología experimental.
¿La experiencia para un desarrollador iOS está completamente resuelta?
No.
Y probablemente esta sea la parte más interesante de la situación actual.
La tecnología base está madura, pero algunas de las piezas que harán que trabajar con ella desde iOS resulte realmente natural todavía están evolucionando.
Swift Export es probablemente el mejor ejemplo.
La integración con Xcode, el debugging y los tiempos de compilación siguen mejorando.
Pero la dirección resulta bastante clara.
¿Lo utilizaría hoy?
Sí, pero no intentaría compartir todo desde el primer día.
Si empezase hoy un proyecto Android+iOS, una estrategia que me parece especialmente razonable sería compartir inicialmente:
Networking
↓
Data sources
↓
Repositories
↓
Business logic / Use cases
y mantener:
Android → UI nativa
iOS → Swift + SwiftUI/UIKit
Después evaluaría qué otras partes merece la pena compartir.
La pregunta que utilizaría para tomar esa decisión no sería:
¿Podemos compartir esto?
Sería:
¿Nos aporta algo compartir esto?
Porque técnicamente cada vez podemos compartir más.
Pero una buena arquitectura multiplataforma no debería intentar maximizar el porcentaje de código compartido.
Debería intentar minimizar el código duplicado sin perder las ventajas de cada plataforma.
Y creo que precisamente ahí es donde Kotlin Multiplatform resulta más interesante en 2026.
No porque permita dejar de desarrollar para iOS.
Sino porque permite seguir desarrollando para iOS sin tener que desarrollar dos veces todo lo demás.
Comments are closed here.