# Kotlin Multiplatform 2026: Android ve iOS ortak kod > Kotlin Multiplatform 2026'da iş mantığını Android ve iOS arasında nasıl paylaşır: Gradle kurulumu, expect/actual, Ktor ağı, Compose Multiplatform arayüzü ve KMP mülakat soruları. - Published: 2026-06-26 - Updated: 2026-07-06 - Author: SharpSkill - Tags: Kotlin Multiplatform, KMP, Android, iOS, Cross-platform - Reading time: 10 min --- Kotlin Multiplatform (KMP), tek bir Kotlin kod tabanının hem Android hem de iOS uygulamalarının iş mantığını çalıştırmasına olanak tanırken her platform tamamen yerel arayüzünü, performansını ve kendi SDK erişimini korur. 2026 yılında KMP artık bir deney değil: kararlı durumda, resmi olarak [Google](https://developer.android.com/kotlin/multiplatform) tarafından destekleniyor ve Netflix, McDonald's, Forbes ile Cash App'te üretimde çalışıyor. Bu ayrıntılı inceleme, kod paylaşımının gerçekte nasıl işlediğini, paylaşılan bir modülün nasıl yapılandırılacağını ve bir KMP mülakatından önce anlaşılması gereken ödünleşimleri ele alır. > **KMP gerçekte neyi paylaşır** > > Kotlin Multiplatform, bir çalışma zamanını değil, derlenmiş mantığı paylaşır. Ortak Kotlin, Android için JVM bayt koduna ve iOS için (LLVM aracılığıyla) yerel bir ikili dosyaya derlenir. JavaScript köprüsü, gömülü webview veya yansıma katmanı yoktur, bu nedenle paylaşılan kod her iki platformda da yerel hızda çalışır. ## Kotlin Multiplatform kodu yerel performanstan ödün vermeden nasıl paylaşır Temel mekanizma, kaynak kümelerinden (source sets) oluşan bir hiyerarşidir. `commonMain`, platformdan bağımsız Kotlin kodunu barındırır: ağ, serileştirme, iş kuralları ve görünüm modelleri. `androidMain` ve `iosMain` gibi platform kaynak kümeleri, platform API'lerine dokunan kodu barındırır. Derleyici, Android için `commonMain` artı `androidMain`'den bir JVM yapıtı, iOS için ise `commonMain` artı `iosMain`'den yerel bir framework üretir. 2026'da Kotlin Multiplatform, tek bir doğruluk kaynağından gerçekten fayda sağlayan şeyleri paylaşmayı tercih eder: modeller, API istemcileri, önbellekleme ve doğrulama. Arayüz, Compose Multiplatform ile paylaşılabilir veya ekran ekran SwiftUI ile tamamen yerel bırakılabilir. Bu "mantığı paylaş, arayüzü seç" modeli, ekiplerin mevcut uygulamaları yeniden yazmadan KMP'yi benimsemesinin nedenidir. Kotlin Multiplatform, tek bir paylaşılan modülü birden çok hedefe (JVM üzerinde Android, yerel olarak iOS, ayrıca masaüstü ve web) derleyen bir Kotlin teknolojisidir; böylece iş mantığı bir kez yazılırken her platform kendi yerel arayüzünü ve tam SDK erişimini korur. Google artık bunu birinci sınıf bir seçenek olarak destekliyor; Room, DataStore, ViewModel ve Paging gibi Jetpack kütüphaneleri KMP yapıtları sunuyor. Paylaşılan modüle neyin ait olduğuna karar vermek, bir KMP projesindeki en önemli mimari karardır. Aşağıdaki tablo, çoğu üretim ekibinin 2026'da bu sınırı nasıl çizdiğini yansıtır: sunum katmanının altındaki her şey paylaşım için güçlü bir adaydır, platform UX kurallarına dokunan her şey ise genellikle yerel kalır. | Katman | commonMain'de paylaşılsın mı? | Neden | |-------|---------------------|--------| | Veri modelleri ve DTO'lar | Evet | Her iki platformda özdeş API sözleşmesi | | Ağ ve önbellekleme | Evet | Tek HTTP yığını, tek hata yüzeyi | | İş kuralları ve doğrulama | Evet | Alan, işletim sistemine göre değişmez | | Görünüm modelleri ve durum | Genellikle | Compose ve SwiftUI paylaşılan durumu tüketir | | Arayüz oluşturma | İsteğe bağlı | Compose ile paylaşılır veya her ekranda yerel | | Platform API'leri (kamera, biyometri) | Hayır | Bunun yerine expect/actual ile açığa çıkarılır | Kazanç, bir uygulamanın bu tablonun alt yarısının ne kadarına sahip olduğuyla ölçeklenir. İnce arayüzlere sahip veri yoğun ürünler en çoğunu paylaşır; son derece özel, animasyon odaklı uygulamalar en azını paylaşır. Hiçbir uç doğru değildir, bu yüzden KMP her şeyi yeniden yazmak yerine kademeli benimsemeye uygundur. ## Paylaşılan modülü Gradle'da yapılandırma Bir KMP modülü, hedeflerini ve kaynak kümelerini Kotlin DSL içinde bildirir. Aşağıdaki `build.gradle.kts`, Android'i ve üç iOS mimarisini (fiziksel cihaz, Intel simülatörü, Apple Silicon simülatörü) kurar ve iOS çıktısını `Shared` adlı bir framework olarak sunar. ```kotlin // shared/build.gradle.kts plugins { kotlin("multiplatform") kotlin("plugin.serialization") id("com.android.library") } kotlin { // Android target compiles commonMain + androidMain to JVM bytecode androidTarget() // Three iOS targets: device, Intel sim, Apple Silicon sim listOf(iosArm64(), iosX64(), iosSimulatorArm64()).forEach { target -> target.binaries.framework { baseName = "Shared" // becomes "import Shared" in Swift isStatic = true } } sourceSets { commonMain.dependencies { implementation("io.ktor:ktor-client-core:3.3.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") } androidMain.dependencies { implementation("io.ktor:ktor-client-okhttp:3.3.0") } iosMain.dependencies { implementation("io.ktor:ktor-client-darwin:3.3.0") } } } ``` Her hedef, platforma özgü bir Ktor motoru çeker (`okhttp` Android'de, `darwin` iOS'ta), paylaşılan kod ise yalnızca ortak `ktor-client-core` API'sine bağlıdır. Tüm seçenek kümesi [Kotlin Multiplatform belgelerinde](https://kotlinlang.org/docs/multiplatform.html) bulunur. ## expect ve actual ile platforma özgü kod yazma Bazı mantık, platform API'sine ihtiyaç duyduğu için `commonMain` içinde yer alamaz. `expect`/`actual` mekanizması, şekli ortak kodda bildirir ve her hedef için somut bir uygulama sağlar; bu, derleme zamanında sıfır çalışma zamanı maliyetiyle çözülür. ```kotlin // commonMain/kotlin/Platform.kt // commonMain declares what it needs but cannot implement here expect class Platform() { val name: String val osVersion: String } // Shared logic can now depend on Platform freely fun analyticsUserAgent(): String { val platform = Platform() return "SharpSkill/" + platform.name + " " + platform.osVersion } ``` Android uygulaması `Build` sınıfından, iOS uygulaması ise `UIDevice`'tan okur. Her ikisi de aynı sözleşmeyi karşılar, bu nedenle `commonMain` hangisiyle konuştuğunu asla bilmez. ```kotlin // androidMain/kotlin/Platform.kt import android.os.Build // actual supplies the Android-specific implementation actual class Platform actual constructor() { actual val name: String = "Android" actual val osVersion: String = Build.VERSION.RELEASE } ``` ```kotlin // iosMain/kotlin/Platform.kt import platform.UIKit.UIDevice // actual uses UIKit directly, no Objective-C bridging code required actual class Platform actual constructor() { actual val name: String = "iOS" actual val osVersion: String = UIDevice.currentDevice.systemVersion } ``` Kotlin/Native, tüm iOS SDK'sı için türlenmiş bağlamalar (bindings) sağlar; böylece `UIDevice`, `NSUserDefaults` ve Foundation türleri elle yazılmış yapıştırıcı kod olmadan Kotlin'den çağrılabilir. ## Ağ ve serileştirme mantığını paylaşma Ağ, paylaşılacak en yüksek değerli koddur, çünkü API sözleşmeleri her iki platformda özdeştir. Tek bir [Ktor](https://ktor.io/docs/) istemcisi ile `kotlinx.serialization`, iki paralel uygulamanın yerini alır. `suspend` fonksiyonları, her iki tarafta da `async`/`await`'e temiz biçimde eşlenen [Kotlin korutinlerine](/blog/android/mastering-kotlin-coroutines) dayanır. ```kotlin // commonMain/kotlin/data/InterviewRepository.kt import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.client.request.get import io.ktor.serialization.kotlinx.json.json import kotlinx.serialization.Serializable // One serializable model, zero duplication across platforms @Serializable data class Question(val id: String, val prompt: String, val difficulty: String) // One HttpClient, one JSON parser, one repository for both apps class InterviewRepository { private val client = HttpClient { install(ContentNegotiation) { json() } } suspend fun fetchQuestions(tech: String): List = client.get("https://api.sharpskill.dev/questions/" + tech).body() } ``` Bu depo, yeniden deneme mantığı ve veri modelleri bir kez yazılır. Ayrıştırıcıda düzeltilen bir hata, Android ve iOS'ta aynı anda düzeltilir; KMP kurulum maliyetini işte burada geri öder. Aynı desen, SQLDelight ile paylaşılan bir veritabanına, paylaşılan anahtar-değer depolamasına ve Koin ile paylaşılan bağımlılık enjeksiyonuna genişler; böylece tüm veri katmanı, arayüzün bağlı olduğu arabirimlerin arkasında `commonMain` içinde yer alabilir. Yaygın bir hata, çok erken çok fazla şey paylaşmaya çalışmaktır. Pragmatik yol, tek bir depoyla başlamak, her iki platformda derleme ve CI hattını kanıtlamak, ardından güven arttıkça özellikleri birer birer taşımaktır. ## Compose Multiplatform ile paylaşılan arayüz oluşturma Compose Multiplatform, Mayıs 2025'te (sürüm 1.8.0) iOS'ta kararlı duruma ulaştı ve 2026 ortasına kadar yerel metin girişi ve varsayılan olarak açık eşzamanlı oluşturmayla 1.11.0'a ulaştı. `commonMain` içindeki bir `@Composable`, her iki platformda oluşturulur ve paylaşılan görünüm modelleri, bir [MVVM veya MVI mimarisiyle](/blog/android/mvvm-vs-mvi-architecture) doğal biçimde eşleşir. ```kotlin // commonMain/kotlin/ui/QuestionList.kt import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.Card import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.foundation.layout.padding // This list renders identically on Android and iOS @Composable fun QuestionList(questions: List) { LazyColumn { items(questions) { question -> Card(modifier = Modifier.padding(8.dp)) { Text(text = question.prompt, modifier = Modifier.padding(16.dp)) } } } } ``` Arayüz paylaşımı isteğe bağlıdır ve ekran ekran yapılır. Bir ekip, arayüzün tamamını [Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform) ile paylaşabilir, tüm uygulama için SwiftUI'yi koruyup yalnızca mantığı paylaşabilir veya ikisini birleştirebilir. Widget'lar veya App Clips gibi platforma özgü UX'e bağlı ekranlar genellikle yerel bırakılır. ## Paylaşılan koda iOS'ta Swift'ten erişme Paylaşılan modül, Swift'in herhangi bir kütüphane gibi içe aktardığı bir framework'e derlenir. Tarihsel olarak sürtünme, Kotlin `suspend` fonksiyonlarının ve `Flow`'un beceriksiz geri arama API'leri olarak ortaya çıkmasıydı. Touchlab'dan [SKIE](https://skie.touchlab.co/), deyimsel Swift üreterek bunu çözer: `suspend` yerel `async`/`await`'e, `Flow` ise `AsyncSequence`'e dönüşür. ```swift // iosApp/ContentView.swift import SwiftUI import Shared // the KMP framework, baseName = "Shared" struct ContentView: View { @State private var questions: [Question] = [] private let repository = InterviewRepository() var body: some View { List(questions, id: \.id) { question in Text(question.prompt) } .task { // With SKIE, the Kotlin suspend fun is a Swift async fun questions = (try? await repository.fetchQuestions(tech: "android")) ?? [] } } } ``` iOS ekibi sıradan Swift ve SwiftUI yazar. Paylaşılan modelleri ve depoları tıpkı yerel bir Swift paketi gibi kullanır, bu da KMP'yi iOS kod tabanının çoğu için görünmez kılar. Bir mülakatta adı anılmaya değer iki pürüz hâlâ var. İlki, derleme süreleri: Kotlin/Native derlemesi saf bir Swift derlemesinden daha yavaştır, ancak Gradle derleme önbelleği ve önceden derlenmiş XCFramework dağıtımı günlük maliyeti yumuşatır. İkincisi, Swift-Kotlin sınırı boyunca hata ayıklama gelişiyor ancak henüz tek bir dilde kalmak kadar sorunsuz değil; bu da ekiplerin paylaşılan yüzeyi yayılmak yerine bilinçli tutmasının bir başka nedenidir. ## Beklenebilecek Kotlin Multiplatform mülakat soruları KMP mülakat soruları Android ve mobil rollerde giderek daha sık göründüğünden, daha geniş bir [Android mülakat hazırlığının](/technologies/android) yanında birkaç tekrar eden soruyu prova etmek faydalıdır: - **expect/actual bir arabirimden nasıl farklıdır?** expect/actual, her hedef için derleme zamanında çözülür, çalışma zamanında dağıtım yapmaz ve bir sınıfı, fonksiyonu, özelliği veya typealias'ı destekleyebilir. Bir arabirim ise çalışma zamanında dinamik olarak çözülür. Platform API'leri için expect/actual, paylaşılan kod içindeki çok biçimlilik için arabirimler kullanılır. - **Kotlin/Native belleği ve iş parçacıklarını nasıl yönetir?** Kotlin 1.7.20'den beri yeni bellek yöneticisi eski nesne dondurma modelini kaldırdı, bu nedenle paylaşılan değiştirilebilir durum ve korutinler, JVM'deki gibi iş parçacıkları arasında çalışır. - **Mevcut bir uygulama KMP'yi kademeli olarak benimseyebilir mi?** Evet. Paylaşılan modül, Android için bir AAR ve iOS için bir XCFramework olarak dağıtılır, böylece tek bir depo veya özellik yeniden yazma olmadan birer birer taşınabilir. - **Arayüz ne zaman Compose Multiplatform kullanmak yerine yerel kalmalıdır?** Bir ekran platforma özgü UX'e dayandığında veya iOS ekibi sunum katmanına sahip olup onu kontrol etmeyi tercih ettiğinde. > **2026'da araç zinciri** > > K2 derleyicisiyle Kotlin 2.3, ağ için Ktor 3.x, paylaşılan veritabanı için SQLDelight ve bağımlılık enjeksiyonu için Koin hedeflenmelidir. iOS birlikte çalışabilirliği için SKIE erken eklenmelidir; Swift katmanı yazıldıktan sonra sonradan eklemek çok daha zahmetlidir. ## Sonuç 2026'da Kotlin Multiplatform, yerel arayüzden veya performanstan ödün vermeden Android ile iOS arasında yinelenen mantığı azaltmanın pragmatik bir yoludur: - Tek bir doğruluk kaynağı olan mantığı paylaşın (modeller, ağ, doğrulama) ve her ekranda yerel veya Compose arayüz seçin. - Platform API'leri için `expect`/`actual` kullanın; derleme zamanında çözülür, çalışma zamanı yükü olmaz. - Ağı Ktor ve `kotlinx.serialization` ile bir kez yazın, böylece düzeltmeler her iki platforma aynı anda ulaşır. - Yeniden yazmaya bağlanmak yerine bir AAR ve XCFramework aracılığıyla kademeli olarak benimseyin. - Swift'in `suspend` ve `Flow`'u yerel `async`/`await` ve `AsyncSequence` olarak kullanması için SKIE'yi baştan ekleyin. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/android/kotlin-multiplatform-2026