Pontos Principais
- Usando Kotlin multi-plataforma, evita-se a repetição de muito código para executar um aplicativo em diversas plataformas;
- O KMP não é a última fase para se obter 100% do código compartilhado entre todas as plataformas, já que a interface de usuário deve ser programada nativamente por ser muito específica para ser compartilhada por cada plataforma;
- As semelhanças entre as sintaxes do Swift e Kotlin reduzem drasticamente parte da curva de aprendizado envolvida na escrita da lógica de negócios do KMP.
- Pode-se usar o Android Studio para criar um componente KMP reutilizável e depois importá-lo no projeto Xcode como um framework.
Kotlin multi-plataforma para desenvolvedores iOS
DRY (do inglês "Don´t Repeat Yourself", não se repita, em português) é um dos princípios fundamentais da programação, mas a repetição de boa parte do código às vezes é necessária para desenvolver aplicativos em diferentes plataformas. Tentar minimizar a repetição é apenas uma boa prática de programação, portanto, mais código compartilhado entre plataformas significa menos repetição, e por consequente um código melhor.
Imagine um projeto para o iOS: está disponível em outras plataformas, como Android ou web? Se sim, quanta lógica o app iOS compartilha com as outras plataformas? Se não for compatível, está nos planos ser, quanto código repetido será necessário implementar novamente? Em ambos os casos, a resposta é muito.
Conheça o Kotlin multi-platforma (KMP). O Kotlin é uma linguagem de programação com tipagem estática que tem uma semelhança impressionante com Swift e é 100% interoperável com Java. De maneira geral, é o Swift do Android. O KMP é uma funcionalidade do Kotlin que compartilha códigos entre várias plataformas, de maneira que cada interface de usuário programada nativamente faz chamadas ao código comum. O KMP não é o processo final para ter 100% do código compartilhado entre todas as plataformas, mas é o caminho natural em direção a este objetivo.
O KMP funciona usando o Kotlin para programar regras de negócio que são comuns às várias plataformas do aplicativo. Dessa forma, a interface de usuário nativamente programada em cada plataforma acessa a lógica comum. A lógica de interface de usuário ainda precisa ser programada nativamente em muitos casos porque é muito específica de cada plataforma para ser compartilhada. Para o iOS, isso significa importar um .frameworkfile - originalmente escrito em KMP - no projeto Xcode, da mesma forma como qualquer outra biblioteca externa. Ainda é necessário Swift para usar KMP no iOS, então o KMP não significa o fim do Swift.
O KMP também pode ser introduzido aos poucos, de maneira que podemos implementá-lo sem quebrar o projeto atual, não precisando substituir o código fonte legado escrito em Swift. Da próxima vez que for necessário a implementação de uma funcionalidade para várias plataformas no aplicativo, podemos usar o KMP para escrever a lógica de negócio, implementar em cada plataforma e programar as interfaces de usuário nativamente. Para o iOS, isso significa regras de negócio em Kotlin e lógica de interface de usuário em Swift.
As semelhanças entre as sintaxes de Swift e Kotlin reduzem massivamente parte da curva de aprendizado envolvida na escrita de lógica de negócio em Kotlin. O que falta nessa curva de aprendizado é a IDE: O Android Studio.
O projeto Kotlin multi-plataforma ainda é experimental, assim, as APIs podem mudar a cada atualização.
Primeiros passos
Este tutorial é direcionado a desenvolvedores iOS com pouca ou nenhuma experiência com Android Studio ou Kotlin. Se ainda não instalou o Android Studio, siga este passo a passo.
Clone o projeto inicial. O mesmo contém um projeto KMP padrão, que inclui uma biblioteca KMP vazia. O projeto inicial também inclui um aplicativo iOS e um aplicativo Android que exibe gifs de uma lista com 25 URLs.
Estes aplicativos são fornecidos, mas a biblioteca não, porque esse artigo está exclusivamente focado na criação de uma biblioteca KMP e não nos aplicativos que usam essa biblioteca. Mas é certo que iremos adquirir conhecimento valioso caso queiramos nos aprofundar no desenvolvimento Android.
Usando o KMP, iremos escrever a lógica de rede que acessa as 25 URLs do Giphy procurando pela frase "whoa" na API pública. Estas URLs irão sobrescrever as que estão codificadas em cada plataforma.
Vamos abrir o Android Studio e selecionar Open an existing Android Studio project. Através da janela Finder que irá abrir, selecionemos o diretório raiz GifGetter/ do projeto inicial clonado.
Se a caixa de diálogo acima aparecer, precisamos clicar no Update.
Android Studio
Caso não conheça o Android Studio, provavelmente terá muita informação para assimilar. Esta é uma introdução sobre os componentes do Android Studio utilizados neste tutorial. Caso queira uma introdução mais completa sobre a IDE, utilize este link.
Vamos começar com o básico: o project navigator à esquerda, que deve mostrar uma estrutura de arquivos. Se não aparecer a estrutura, selecione a aba Project no canto superior esquerdo, que mostrará o project navigator. Acima do project navigator, observe um menu dropdown com o nome Android. Clique nele e selecionar a opção Project no menu.
1. A linha de botões ao topo do Android Studio é o toolbar. As ferramentas disponíveis nele possuem diversas funções, como construir a aplicação, iniciar, depurar, aplicar novas mudanças e iniciar o Android Virtual Device (AVD) Manager. Abaixo, temos a barra de navegação, que mostra a localização do arquivo aberto no diretório, que nesse caso é /GifGetter/GifLibrary/commonMain/kotlin/platform/common.kt.
- Seguem algumas das funcionalidades da toolbar:
- O martelo é o botão de Build;
- O menu ao lado é o menu de configurações;
- Ao lado temos o botão Run, assim como no Xcode.
2. A documentação oficial do Android se refere a este espaço como uma das janelas de ferramenta, mas é usualmente conhecida como estrutura de projeto, estrutura de arquivos, ou outros termos similares. É como se fosse o project navigator do Xcode.
- Observe o menu Project no topo. Deve estar escrito Project neste tutorial. Se estiver escrito Android ou qualquer outra coisa, selecione Project novamente pois não poderemos ver todos os diretórios e arquivos na estrutura abaixo.
3. Esta é a janela de edição, na qual se escreve o código. Observe os arquivos acima, android.kt, common.kt, ios.kt e GifLibrary, estas são as abas abertas em plano de fundo. Clique com o botão direito em uma delas para ver as opções de mais janelas de edição à direita, à esquerda, acima ou abaixo.
4. Esta é parte da barra de janela de ferramentas, que envolve a parte externa do Android Studio. A única parte relevante é a circulada em amarelo, particularmente as abas Terminal e Build
Estrutura de projeto
Abaixo, uma visão ampla da estrutura de projeto KMP:
- Diretórios .gradle/ e .idea/: arquivos locais que não devem ser confirmados para a maioria dos projetos de Android Studio. As pastas incluem configurações locais da IDE, do projeto e dependências, dessa forma não são relevantes para este tutorial.
- Diretório androidApp/: o diretório raiz para o aplicativo Android no nosso projeto KMP que possui toda a lógica de interface de usuário do Android.
- Diretório build/: possui o conteúdo dos builds KMP. Também não deve ser versionado.
- Diretório iosApp/: o diretório raiz para o projeto Xcode dentro do projeto KMP.
- Diretório GifLibrary: o diretório da lógica KMP. Contém a lógica de negócio para o projeto Android e será convertida pelo KMP em um GifLibrary.framework para o projeto iOS. O diretório src/ contém o seguinte:
- androidLibMain: lógica KMP específica para Android;
- commonMain: lógica de negócio KMP agnóstica a plataforma;
- iosMain: lógica KMP específica para iOS para interagir com APIs Apple (como UIKit, GCD etc…);
- main: contém o arquivo AndroidManifest.xml, que define GifLibrary/ como uma biblioteca Android. Em muitas situações, é como se fosse um Xcode.plist.
- build.gradle: um conceito novo, visto que não há nenhum correlato direto no desenvolvimento iOS. Em linhas gerais, é um script de build ou makefile que define dependências, scripts e outras configurações para o projeto. Nesse sentido, é como um arquivo .xcodeproj.
- External Libraries: Todas as dependências do projeto. Projetos Android e KMP diferem de projetos iOS no quesito de necessitarem de mais dependências externas.
Os demais arquivos no nível acima do projeto (exemplo: local.properties e todos os arquivos .iml) são gerados pelo Android Studio e não são relevantes para o que iremos fazer com KMP. Por outro lado, o arquivo settings.gradle é um arquivo de configuração que deve ser versionado. Diferente do arquivo build.gradle, settings.gradle não é um script de build, mas um arquivo de configuração do gradle.
Agora que entendemos o básico de Android Studio, está na hora de se aprofundar num projeto KMP!
Configurando o Gradle para KMP
*OBS: como mencionado, o KMP ainda é experimental. Dessa forma, as configurações do gradle são suscetíveis a mudança.*
Abra o arquivo GifLibrary/build.gradle e olhe para o bloco de código em kotlin()
:
kotlin {
targets {
fromPreset(presets.android, 'androidLib')
def buildForDevice = project.findProperty("device")?.toBoolean() ?: false
def iosPreset = (buildForDevice) ? presets.iosArm64 : presets.iosX64
def iOSTarget = System.getenv('SDK_NAME')?.startsWith('iphoneos') \
? presets.iosArm64 : presets.iosX64
fromPreset(iosPreset, 'ios') {
binaries {
framework {
// Desabilitar o bitcode incorporado para a construção do simulador.
if (!buildForDevice) {
embedBitcode("disable")
}
}
}
}
fromPreset(iOSTarget, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
}
}
sourceSets {
commonMain {
dependencies {
implementation "io.ktor:ktor-client-json:$ktor_version"
}
}
}
}
Esta é uma configuração de gradle padrão para iniciar um projeto KMP. Primeiramente, observe o bloco targets {}
dentro de kotlin {}
. Sem entrar muito nos detalhes, fromPreset() {}
provê configurações predefinidas para o KMP. Os presets do iOS precisam de linhas adicionais porque diferem por dispositivo e simuladores.
Em seguida, observe o bloco sourceSets {}
. No momento, commonMain
é o único sourceSet
com dependências adicionais. Após commonaMain {}
, adicione o código abaixo ao sourceSets {}
:
androidLibMain {
dependencies {
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
}
}
iosMain {
dependencies {
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-native:$ktor_version"
}
}
Após esta alteração, deverá aparecer uma mensagem dizendo: Gradle files have changed since the last project sync. A project sync may be necessary for the IDE to work properly. Ignore esta mensagem por enquanto, pois há outras modificações a serem feitas no arquivo gradle.
Agora todas as três dependências necessárias estão incluídas no sourceSets
, mas há ainda uma última modificação a ser feita para que o arquivo gradle esteja pronto. Abaixo do bloco kotlin {}
, há uma task
chamada copyFramework
que copia o projeto KMP como um framework iOS no diretório apropriado, de maneira que o projeto iosApp/ possa encontrá-lo. Para garantir que estas tarefas sejam realizadas quando o projeto é construído, insira a seguinte linha após o copyFramework{}
:
tasks.build.dependsOn copyFramework
Agora clique em Sync Now para atualizar o arquivo gradle. Isto pode levar alguns minutos se for necessário realizar o download das novas dependências. Podemos verificar o progresso da sincronização do gradle na aba na parte de baixo do Android Studio .
Explorando a API do Giphy
Vá agora para a API do Giphy para criar uma conta de desenvolvedor. Ou, se já possuir uma conta de desenvolvedor, apenas faça o log in. Então, clique em Create an App e digite "GifGetter" quando requisitado, e uma descrição qualquer. Copie a nova Chave API.
Agora volte para o Android Studio e abra GifLibrary/src/commonMain/kotlin/GiphyAPI e encontre a seguinte classe:
class GiphyAPI {
val apiKey: String = ""
}
Cole a chave da API do Giphy no valor da declaração val
, que é uma string vazia. Esta é a maneira como uma classe e uma string constante são declaradas em Kotlin. Observe que todo este código até então poderia ser Swift, com a única exceção da palavra val
, que é a equivalente ao let
no Kotlin.
Código específico da plataforma
O KMP trata as diferenças entre as plataformas iOS e Android informando ao código comum o que esperar das diversas plataformas. Vá para GifLibrary/src/commonMain/kotlin/platform/, e selecione File → New → Kotlin File/Class para criar um novo Kotlin File/Class chamado common.
No menu Kind abaixo, selecione File.
Estes aplicativos Android e iOS realizarão requisições de rede, então vão precisar executar códigos assíncronos. O iOS utiliza o Grand Central Dispatch (GCD) para tais operações em concorrência, mas não é possível usar esse código em comum porque o Android não usa GCD. Então, ao invés disso, informe ao código comum o que esperar de cada plataforma. Neste caso, é necessário esperar o seguinte dispatcher
:
import kotlinx.coroutines.CoroutineDispatcher
internal expect val dispatcher: CoroutineDispatcher
A IDE acusará um erro porque os módulos iosMain/ e androidLibMain/ estão agora esperando a declaração de uma constante de nome dispatcher
do tipo CoroutineDispatcher
. Comece pelo iOS indo em GifLibrary/src/iosMain/platform/ e crie um arquivo chamado iOS com o seguinte código:
internal actual val dispatcher: CoroutineDispatcher = NsQueueDispatcher(dispatch_get_main_queue())
internal class NsQueueDispatcher(private val dispatchQueue: dispatch_queue_t) : CoroutineDispatcher() {
override fun dispatch(context: CoroutineContext, block: Runnable) {
dispatch_async(dispatchQueue.freeze()) {
block.run()
}
}
}
Este código informa que, para a plataforma iOS, o KMP utilizará GCD e usar a fila principal para executar o código assíncrono. Agora vá para o diretório correspondente no módulo android: GifLibrary/src/androidLibMain/platform/. Crie um outro arquivo com nome Android. Por sorte, a plataforma Android facilita a obtenção do dispatcher principal:
internal actual val dispatcher: CoroutineDispatcher = Dispatchers.Main
O erro de compilação deve desaparecer, já que o dispatcher que o commonMain espera de ambas as plataformas está suportado com as respectivas implementações.
Se preparando para os dados
Precisamos de classes para representar os dados JSON que receberemos da API Giphy. Crie um novo arquivo Kotlin em GifLibrary/src/commonMain/kotlin/ com o nome Data. Cole o seguinte código no novo arquivo:
import kotlinx.serialization.Serializable
@Serializable
data class GifResult(
val `data`: List<Data>
)
@Serializable
data class Data(
val images: Images
)
@Serializable
data class Images(
val original: Original
)
@Serializable
data class Original(
val url: String
)
No topo do arquivo, é necessário importar o Serializable
para que o @Serializable
seja reconhecido. Pense em classes de dados como structs no Swift, ou seja, não são objetos de tipo valor, mas se comportam de maneira similar. A resposta JSON da API Giphy será mapeada para estas classes. Agora commonMain
está pronto para a regra de negócios mais substancial.
Escrevendo a lógica de negócios KMP
Volte para o arquivo GiphyAPI e cole o seguinte código depois da apiKey
:
private val client: HttpClient = HttpClient { // 1
install(JsonFeature) { // 2
serializer = KotlinxSerializer(Json.nonstrict).apply { // 3
setMapper(GifResult::class, GifResult.serializer()) // 4
}
}
}
private fun HttpRequestBuilder.apiUrl(path: String) { // 5
url { // 6
takeFrom("https://api.giphy.com/") // 7
encodedPath = path // 8
}
}
Segue um passo-a-passo do que o código acima faz:
- Declare uma constante do tipo
HttpClient
. Novamente, a única diferença entre esta linha e o equivalente em Swift é a palavraval
no lugar delet
. - Instale o
JsonFeature
no objetoclient
para que seja possível serializar e deserializar o JSON. - Crie e configure o
serializer
, uma propriedade de objetosHttpClient
que énull
por padrão. O formato Json.nonstrict indica que a resposta JSON pode conter campos irrelevantes para as classes de dados na próxima linha. - Forneça a classe para o
serializer
, a qual vai serializar a resposta JSON em um objetoGifResult
. O campo "data" no JSON irá popular a propriedadeGifResult.data
correspondente. Os campos continuarão populando hierarquicamente para as classes de dados aninhadas. - Adicione a função
apiUrl(path: String)
à classeHttpRequestBuilder
. - Construa uma URL.
- Forneça a URL base.
- Estenda a URL com o caminho especificado.
Agora que o código repetitivo da lógica de rede está criado, é hora de criar uma chamada para o endpoint Giphy para pesquisar resultados "whoa". Abaixo do código que acabamos de colar, adicione o seguinte:
suspend fun callGiphyAPI(): GifResult = client.get {
apiUrl(path = "v1/gifs/trending?api_key=$apiKey&limit=25&rating=G")
}
Mas espere, o que é a palavra reservada suspend
e para que serve? Bem, é uma das maneiras de executar código assíncrono no Kotlin através de coroutines
. Por hora, apenas saiba que significa que a função só pode ser chamada por uma uma coroutine
ou outra função suspend, como a função get{}
em HttpClient
.
O próximo passo é configurar uma função que estará disponível para os aplicativos Android e iOS. De novo, a sintaxe é bem parecida com o Swift:
fun getGifUrls(callback: (List) -> Unit) { // 1
GlobalScope.apply { // 2
launch(dispatcher) { // 3
val result: GifResult = callGiphyAPI() // 4
val urls = result.data.map { // 5
it.images.original.url // 6
}
callback(urls) // 7
}
}
}
Declare a função getGifUrls(callback: (List
. Esta função é o que os códigos Android e iOS irão chamar. O tipo de retorno Unit
é o equivalente em Kotlin do void
em Swift.
- Executa o seguinte código no contexto de
GlobalScope
, que inclui o próprio dispatcher e lógica de cancelamento de tarefa. - Executa nosso
dispatcher
, e não o padrão. Lembre-se que a implementação dodispatcher
é específica de cada plataforma. Declara um valor equivalente ao que é retornado da funçãocallGiphyApi()
. - Mapeia a lista de dados do objeto
GifResult
... - … indo até a propriedade
url
de cada um. Aurl
é uma string, então o mapeamento resultará num objetoList
. A palavra reservadait
do Kotlin representa o parâmetro do lambda, no caso em que há apenas um. - Passa a lista de URLs para a chamada de retorno fornecido como um parâmetro da função.
Implementando o KMP no Android
O passo final para o aplicativo Android é substituir a lista existente de URLs com URLs recebidas da API do Giphy. Isto não é tão difícil quanto parece.
Abra o arquivo androidApp/src/main/kotlin/MainActivity. O Activity
do Android está profundamente relacionado com o ViewController
, e a primeira função implementada aqui no MainActivity
é onCreate(savedInstanceState: Bundle?)
, que é de alguma forma similar ao viewDidLoad()
:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val gifList: RecyclerView = findViewById(R.id.gif_list)
val layoutManager = LinearLayoutManager(this)
gifList.layoutManager = layoutManager
adapter = GifAdapter(this)
gifList.adapter = adapter
adapter.setResults(urls)
}
Agora, remova a última linha da função em que os resultados estão sendo carregados com fakeData
, e substitua com a seguinte:
getGifUrls {
adapter.setResults(it)
}
A função setResults(result: List
vai configurar as URLs de gif como nova fonte de dados e recarregar o RecyclerView
, que é essencialmente a versão do Android para ambas UITableView
e UICollectionView
, embora haja diferenças chave que devemos pesquisar mais se tivermos interesse. E essa é toda a lógica do lado do Android!
Se não funcionar o Auto Import e houver erros de referência não resolvidos, podemos ter que adicionar o seguinte na lista de imports no topo do arquivo:
import org.gifLibrary.GiphyAPI
Executando no emulador Android
Clique no botão Run na barra de tarefas no topo do Android Studio. O ícone é muito parecido com o botão Run do Xcode. Uma janela aparecerá com o gerenciador de dispositivos virtuais do Android (do inglês Android Virtual Devices, AVD), que é similar à janela de gerenciamento de simuladores do Xcode. A diferença é que Xcode vem com simuladores pré instalados.
Na nova janela, se tiver algum dispositivo Android disponível na lista, o selecione para executar o aplicativo. Caso contrário, pressione Create New Virtual Device. Selecione a categoria Phone e Pixel 2 XL na lista de dispositivos e posteriormente clique no botão Next no canto inferior direito.
Em seguida, selecione Download ao lado da versão mais recente do Android, a qual possui o melhor nível de API. Outra janela aparecerá para instalar a versão selecionada do Android. Se não visualizar o botão Download ao lado da versão do Android, estamos com sorte! Selecione esta versão e clique em Next novamente. Pegue uma xícara de café enquanto o sistema operacional do Android carrega e, quando voltar com o novo dispositivo Android, selecione Finish.
Tudo pronto do lado do Android! Aproveite seu novo aplicativo Android e a lógica de rede KMP. A seguir, vamos voltar para terras mais conhecidas.
Configuração do Xcode
Abra o projeto Xcode e vá para o Build Phases do target do iosApp e clique no botão +, circulado em vermelho:
Selecione a opção New Run Script Phase. É possível ver um novo Run Script no final da lista na janela principal. Agora arraste para cima da lista de maneira que fique acima de Compile Sources. Agora, clique na seta ao lado e cole o seguinte script:
cd "$SRCROOT/../"
./gradlew GifLibrary:copyFramework \
-Pconfiguration.build.dir="$CONFIGURATION_BUILD_DIR" \
-Pkotlin.build.type="$KOTLIN_BUILD_TYPE" \
-Pdevice="$KOTLIN_DEVICE"
Este script de execução lê o Build Settings do projeto Xcode para estas definições serem utilizadas na tarefa copyFramework
do gradle, que pode ser visualizada ao voltar para o GifGetter/GifLibrary/build.gradle. Mas o projeto Xcode ainda não tem essas configurações. Para criá-las, vá para a aba Build Settings do target e pressione o botão +, como demonstrado abaixo:
Selecione Add User-Defined Setting no pequeno menu que aparece. Nomeie a nova configuração "KOTLIN_BUILD_TYPE". Agora clique na seta ao lado para revelar os ambientes Debug e Release. Configure o Debug com o valor "DEBUG" e Release com o valor "RELEASE".
Adicione outra User-Defined Setting com o nome "KOTLIN_DEVICE". Depois clique no botão + à direita de Debug. Isto criará um campo abaixo de Debug com o nome Any Architecture | Any SDK. Clique para ver uma lista de possíveis arquiteturas e escolha Any iOS Simulator SDK. Configure este campo com o valor false. Faça o mesmo com o Debug, mas desta vez adicione Any iOS SDK e configure com o valor true.
Repita estes passos no Release abaixo de "KOTLIN_DEVICE". Depois destes passos, a User-Defined Settings deve se parecer com a seguinte:
Depois, na barra de pesquisa na parte de cima, pesquise por "Framework Search Paths":
Adicione o seguinte em Framework Search Paths para Debug e Release:
"$(SRCROOT)/../GifLibrary/build"
Esse diretório é onde o KMP cria um arquivo .framework que contém a lógica de negócios necessária para o app iOS. Se formos em GifGetter/GifLibrary/build/ no Finder, veremos um arquivo GifLibrary.framework pronto para ser utilizado pelo Xcode.
Em seguida, vá para a aba General do target do iOSApp, role até embaixo e clique no botão + abaixo de Embedded Binaries. Na janela que aparecer, cliquer em Add Other na parte de baixo. Na janela do Finder, selecione o arquivo GifLibrary.framework em GifGetter/GifLibrary/build/ e clique em Open. Isto também deve adicionar o framework em Linked Binaries and Frameworks.
Agora abra o GifRetriever.swift e observe um vetor hardcoded com 25 strings de URLs. Logo abaixo, veja a função requestGifs(_closure: @escaping StringsClosure)
passando as URLs. Mais abaixo da declaração import Foundation
no topo do arquivo, adicione import GifLibrary
.
Agora, substitua o corpo da função requestGifs(_closure: @escaping StringsClosure)
de maneira que se pareça com o seguinte:
func requestGifs(_ closure: @escaping StringsClosure) {
GiphyAPI().getGifUrls { gifs -> KotlinUnit in
closure(gifs)
return KotlinUnit()
}
}
O aplicativo iOS está pronto para ser executado no Simulador! Agora temos um aplicativo em duas plataformas diferentes que estão compartilhando a mesma lógica através do KMP!
Próximos passos
Verifique o projeto final no GitHub para referência, caso tenha algum interesse. Lembre-se que o KMP ainda é experimental e altamente suscetível a mudanças, mas está se desenvolvendo e melhorando rapidamente. Não apenas isso, KMP já foi usado com sucesso para construir aplicativos atualmente disponíveis na Apple Store. O KMP é a próxima escolha natural para qualquer desenvolvedor iOS que quiser ramificar o desenvolvimento dos aplicativos em outras plataformas.
O KMP não é apenas o caminho mais rápido para um engenheiro iOS se tornar um desenvolvedor mobile em duas plataformas, mas também significa criar um repositório de regra de negócios que possa ser implantado em outras plataformas. Se quiser depois publicar o aplicativo para um ambiente JavaScript, a regra de negócios escrita para tal já está pronta.
Se quiser se aprofundar em KMP ou em Kotlin em geral, acesse este site, que inclui links para os canais subreddit e Slack do Kotlin. O Touchlab fez um webinar sobre o assunto. Finalmente, voltando um passo, seguem alguns artigos adicionais sobre KMP da Touchlab que pode ser interessante:
Sobre o autor
Ben Whitley é um desenvolvedor iOS residente na cidade de Nova Iorque com 4 anos de experiência em Xcode, Swift e, originalmente, Objective-C. No último 1 ano e meio, foi o principal desenvolvedor iOS da Touchlab, tempo no qual trabalhou próximo de muitos clientes de alto perfil. Atualmente está focado em promover o Kotlin Multi-plataforma como uma plataforma nativa para desenvolvedores iOS, e ajudar desenvolvedores Android a migrarem para o KMP com as questões relacionadas a iOS e Xcode.