KMP’nin ne olduğunu ve neden önemli olduğunu daha önce ele almıştık. Şimdi kolları sıvama vakti: gerçek bir proje oluşturun, içindeki her dosyayı anlayın, paylaşılan kod yazın ve hem Android hem iOS’ta çalıştırın.
Bu uzun bir rehber. Acele etmeyin. Sonunda çalışan bir çapraz platform (cross-platform) uygulamanız olacak ve her parçanın nasıl bir araya geldiğini tam olarak anlayacaksınız.
Bölüm 1: Ortamınızı Kurmak
Neye İhtiyacınız Var
| Araç | Gerekli mi | Amacı |
|---|---|---|
| Android Studio | Evet | KMP geliştirme için IDE (en son kararlı sürüm) |
| Xcode | Evet (sadece Mac) | iOS uygulamalarını derler ve çalıştırır |
| JDK 17+ | Evet | Kotlin derleyicisi buna bağımlı |
| Mac bilgisayar | iOS için | Apple, yalnızca macOS’ta çalışan Xcode’u zorunlu kılıyor |
| CocoaPods | İsteğe bağlı | Bazı KMP kütüphaneleri iOS için buna ihtiyaç duyar |
Windows veya Linux kullanıyorsanız, yine de paylaşılan kod yazabilir ve Android uygulamasını derleyebilirsiniz. Ancak iOS’u derleyemez ya da çalıştıramazsınız. Bunun bir yolu yok, Apple, iOS derlemelerini kontrol ediyor.
Adım 1: Android Studio’yu Kurun
En son kararlı sürümü developer.android.com/studio adresinden indirin. Kurun ve şunlara sahip olduğunuzdan emin olun:
- Android SDK (API 34 veya üzeri)
- Bir Android emülatörü (veya fiziksel cihaz)
Adım 2: Kotlin Multiplatform Eklentisini Kurun
Bu, çoğu rehberin atladığı adım, sonra da neden iOS çalıştırma yapılandırmalarını görmediğinize şaşırırsınız.
- Android Studio’yu açın
- Settings → Plugins → Marketplace yolunu izleyin
- “Kotlin Multiplatform” araması yapın
- Kurun ve Android Studio’yu yeniden başlatın
Bu eklenti olmadan, Android Studio, KMP projelerini nasıl ele alacağını bilmez.
Adım 3: Xcode’u Kurun (Sadece Mac)
Xcode’u Mac App Store’dan indirin. Kurduktan sonra:
# Komut satırı araçlarını kur
sudo xcode-select --install
# Lisansı kabul et
sudo xcodebuild -license accept
Xcode’u en az bir kez açın, böylece ek bileşenleri kurar.
Adım 4: kdoctor ile Her Şeyi Doğrulayın
kdoctor, tüm KMP ortamınızı tek seferde kontrol eden bir komut satırı aracı:
# kdoctor'ı kur
brew install kdoctor
# Kontrolü çalıştır
kdoctor
Şunları kontrol eder:
- Java sürümü
- Android Studio ve SDK
- Xcode ve komut satırı araçları
- CocoaPods (kuruluysa)
- Kotlin eklenti sürümü
Devam etmeden önce bildirdiği sorunları çözün. Yeşil onay işaretleri hazır olduğunuz anlamına gelir.
Homebrew’unuz yoksa manuel kontrol edin:
java -version # 17+ gerekli
xcode-select --version # Xcode CLT kurulu mu
Bölüm 2: Projeyi Oluşturmak
KMP Wizard’ı Kullanmak (Önerilen)
kmp.jetbrains.com adresindeki KMP Wizard, bir proje oluşturmanın en kolay yolu. Gradle yapılandırma başağrısı yok.
Adım 1: kmp.jetbrains.com adresine gidin
Adım 2: Proje detaylarını doldurun:
- Project name:
MyKmpApp(ya da istediğiniz herhangi bir şey) - Project ID:
com.ornek.mykmpapp
Adım 3: Platformlarınızı seçin:
- Android‘i işaretleyin
- iOS‘u işaretleyin
- İsteğe bağlı olarak Desktop veya Web‘i işaretleyin
Adım 4: UI paylaşımını seçin:
- “Share UI with Compose Multiplatform”: tüm platformlar için tek bir Compose UI. Öğrenmek ve prototip oluşturmak için iyi.
- “Do not share UI”: her platformda native UI (Android’de Compose, iOS’ta SwiftUI). Platforma özgü görünüm ve his gerektiren üretim uygulamaları için daha iyi.
Bu rehber için “Share UI with Compose Multiplatform” seçeneğini seçin, böylece ayrı bir Swift kodu yazmadan paylaşılan koda odaklanabiliriz.
Adım 5: Download butonuna tıklayın, dosyayı açın ve klasörü Android Studio’da açın.
Android Studio’yu Kullanmak
Alternatif olarak, Android Studio sürümünüz destekliyorsa:
- File → New → New Project
- Şablon listesinden Kotlin Multiplatform‘u seçin
- Proje adınızı ve paketinizi ayarlayın
- Platformları seçin (Android + iOS)
- Finish’e tıklayın
İlk Gradle Senkronizasyonu
Proje açıldıktan sonra, Android Studio Gradle senkronizasyonuna başlar. Bu, tüm bağımlılıkları indirir.
İlk senkronizasyon 5-10 dakika sürer. Bu normaldir. KMP projeleri, Kotlin/Native derleyicisini, iOS framework üretecilerini ve çok platformlu kütüphaneleri içerdiği için normal Android projelerinden daha fazla bağımlılığa sahiptir.
Senkronizasyon başarısız olursa şunları kontrol edin:
- İnternet bağlantısı
- Proxy ayarları
- JDK sürümü (17+ gerekli)
Bölüm 3: Proje Yapısını Anlamak
Proje açıldıktan sonra şuna benzer bir yapı görürsünüz:
MyKmpApp/
├── shared/ ← PAYLAŞILAN MODÜL
│ ├── build.gradle.kts ← Hedefleri ve bağımlılıkları yapılandırır
│ └── src/
│ ├── commonMain/ ← HER YERDE çalışan kod
│ │ └── kotlin/
│ │ ├── Platform.kt ← expect bildirimi
│ │ └── Greeting.kt ← paylaşılan iş mantığı
│ ├── commonTest/ ← Paylaşılan kod için testler
│ │ └── kotlin/
│ ├── androidMain/ ← Android'e özgü kod
│ │ └── kotlin/
│ │ └── Platform.android.kt ← Android için actual
│ └── iosMain/ ← iOS'a özgü kod
│ └── kotlin/
│ └── Platform.ios.kt ← iOS için actual
│
├── composeApp/ ← UYGULAMA MODÜLÜ
│ ├── build.gradle.kts
│ └── src/
│ ├── commonMain/ ← Paylaşılan Compose UI
│ │ └── kotlin/
│ │ └── App.kt ← Ana uygulama composable'ı
│ ├── androidMain/ ← Android giriş noktası
│ │ └── kotlin/
│ │ └── MainActivity.kt
│ │ └── AndroidManifest.xml
│ └── iosMain/ ← iOS giriş noktası
│
├── iosApp/ ← iOS XCODE PROJESİ
│ └── iosApp/
│ ├── ContentView.swift ← SwiftUI sarmalayıcı
│ └── iOSApp.swift ← iOS uygulama giriş noktası
│
├── build.gradle.kts ← Kök derleme yapılandırması
├── settings.gradle.kts ← Modül bildirimleri
├── gradle.properties ← Proje özellikleri
└── gradle/
└── libs.versions.toml ← Bağımlılık sürümleri
Bu çok fazla klasör. Her birini açıklayalım.
shared/: KMP Projenizin Kalbi
Paylaşılan Kotlin kodunuzun yaşadığı yer burası. commonMain içindeki her şey her platformda çalışır. androidMain içindeki her şey sadece Android’de çalışır. iosMain içindeki her şey sadece iOS’ta çalışır.
Kural basit:
- Kodunuz herhangi bir platformda çalışabilir mi? →
commonMain‘e koyun - Android API’larına mı ihtiyaç duyuyor? →
androidMain‘e koyun - Apple API’larına mı ihtiyaç duyuyor? →
iosMain‘e koyun
composeApp/: Paylaşılan Kodu Kullanan Uygulama
“Share UI with Compose Multiplatform” seçtiyseniz, bu modül tüm platformlarda çalışan Compose UI’ı içerir. Kendi commonMain‘i (paylaşılan UI), androidMain‘i (Android giriş noktası) ve iosMain‘i (iOS giriş noktası) vardır.
“Do not share UI” seçtiyseniz, bunun yerine sadece Android uygulamasını içeren androidApp/ olurdu.
iosApp/: Xcode Projesi
Bu, iOS uygulama projesi. Compose Multiplatform ile bile, iOS için giriş noktası olarak bir Xcode projesine ihtiyacınız var. ContentView.swift dosyası, Compose UI’ınızı iOS için sarmalıyor.
Bölüm 4: Varsayılan Kodu Anlamak
expect/actual Deseni
shared/src/commonMain/kotlin/Platform.kt dosyasını açın:
// commonMain: NEYE ihtiyacımız olduğunu bildirir
// "expect" şu anlama gelir: her platform kendi uygulamasını sağlamalı
expect fun getPlatformName(): String
Bu şunu söylüyor: “Bir String döndüren getPlatformName adında bir fonksiyona ihtiyacım var. Her platform ne döndüreceğine kendi karar verir.”
shared/src/androidMain/kotlin/Platform.android.kt dosyasını açın:
// androidMain: Android yanıtını sağlar
actual fun getPlatformName(): String = "Android ${android.os.Build.VERSION.SDK_INT}"
shared/src/iosMain/kotlin/Platform.ios.kt dosyasını açın:
// iosMain: iOS yanıtını sağlar
import platform.UIKit.UIDevice
actual fun getPlatformName(): String = UIDevice.currentDevice.systemName() +
" " + UIDevice.currentDevice.systemVersion
Dikkat edin:
- commonMain’de
expect→ “Buna ihtiyacım var” - androidMain’de
actual→ “İşte Android sürümü” - iosMain’de
actual→ “İşte iOS sürümü”
Derleyici, her expect bildiriminin her platformda karşılık gelen bir actual‘a sahip olduğundan emin olur. Birini unutursanız, proje derlenmez. Eksik uygulamalardan kaynaklanan çalışma zamanı çökmesi yok.
Greeting Sınıfı
shared/src/commonMain/kotlin/Greeting.kt dosyasını açın:
class Greeting {
fun greet(): String {
return "Hello from ${getPlatformName()}!"
}
}
Bu paylaşılan koddur. Her platformda farklı değerler döndüren getPlatformName()‘i çağırır:
- Android’de: “Hello from Android 35!”
- iOS’ta: “Hello from iOS 18.2!”
Aynı kod, farklı davranış. KMP’nin gücü bu.
Bölüm 5: Uygulamayı Çalıştırmak
Android’de Çalıştırma
- Android Studio’da, araç çubuğu açılır menüsünden composeApp çalıştırma yapılandırmasını seçin
- Bir Android emülatörü veya bağlı cihaz seçin
- Run düğmesine (yeşil üçgen) tıklayın
Ya da terminalden:
./gradlew :composeApp:assembleDebug
./gradlew :composeApp:installDebug
Karşılama mesajını gösteren bir ekran görmelisiniz.
iOS’ta Çalıştırma
Android Studio’dan (KMP eklentisiyle):
- Açılır menüden iosApp çalıştırma yapılandırmasını seçin
- Bir iOS simülatörü seçin (örneğin iPhone 16)
- Run’a tıklayın
İlk iOS derlemesi, Kotlin/Native framework’ünü derlemesi gerektiği için Android’den daha uzun sürer. Sonraki derlemeler daha hızlıdır.
Xcode’dan:
iosApp/iosApp.xcodeprojdosyasını Xcode’da açın- Cihaz açılır menüsünden bir simülatör seçin
- Run düğmesine (veya Cmd+R) tıklayın
Yaygın iOS derleme sorunu: “framework not found Shared” hatası alırsanız şunu çalıştırın:
./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
Bu, iOS’un ihtiyaç duyduğu paylaşılan framework’ü derler.
Desktop’ta Çalıştırma (Wizard’da Seçildiyse)
./gradlew :composeApp:run
Aynı Compose UI ile bir masaüstü penceresi açılır. Aynı kod, üçüncü platform.
Bölüm 6: İlk Gerçek Paylaşılan Kodunuzu Yazmak
Karşılama mesajının ötesine geçip faydalı bir şey yazalım.
Paylaşılan Veri Modelleri
shared/src/commonMain/kotlin/models/User.kt dosyasını oluşturun:
package com.ornek.mykmpapp.models
// Bu data class Android, iOS, Desktop ve Web'de çalışır
// Bir kez tanımla, her yerde kullan
data class User(
val id: String,
val name: String,
val email: String,
val joinedYear: Int = 2026
) {
// Doğrulama mantığı: tüm platformlarda paylaşılır
fun isValid(): Boolean {
return name.isNotBlank() &&
email.contains("@") &&
email.contains(".")
}
// Biçimlendirme mantığı: her platformda aynı
fun displayName(): String {
return if (name.isNotBlank()) name
else email.substringBefore("@")
}
// İş mantığı: her yerde tutarlı
fun membershipYears(): Int {
return 2026 - joinedYear
}
}
Bu User sınıfı, Android ve iOS’ta aynı şekilde çalışır. Doğrulama kuralları, biçimlendirme, iş mantığı, hepsi bir kez yazıldı. isValid() içindeki bir hatayı düzeltirseniz, her iki platformda da aynı anda düzelir.
Paylaşılan Yardımcı Fonksiyonlar
shared/src/commonMain/kotlin/utils/StringUtils.kt dosyasını oluşturun:
package com.ornek.mykmpapp.utils
// Tüm platformlarda kullanılabilir yardımcı fonksiyonlar
object StringUtils {
fun capitalizeWords(text: String): String {
return text.split(" ")
.joinToString(" ") { word ->
word.replaceFirstChar { it.uppercase() }
}
}
fun truncate(text: String, maxLength: Int, suffix: String = "..."): String {
return if (text.length <= maxLength) text
else text.take(maxLength - suffix.length) + suffix
}
fun isValidEmail(email: String): Boolean {
return email.contains("@") &&
email.contains(".") &&
email.indexOf("@") < email.lastIndexOf(".")
}
fun slugify(text: String): String {
return text.lowercase()
.replace(Regex("[^a-z0-9\\s-]"), "")
.replace(Regex("\\s+"), "-")
.trim('-')
}
}
Paylaşılan İş Mantığı
shared/src/commonMain/kotlin/repository/UserRepository.kt dosyasını oluşturun:
package com.ornek.mykmpapp.repository
import com.ornek.mykmpapp.models.User
// Repository deseni: paylaşılan veri erişim mantığı
// Gerçek bir uygulamada bu bir API veya veritabanı çağırırdı
// Şimdilik bellek içi veri kullanıyoruz
class UserRepository {
private val users = mutableListOf(
User("1", "Alex", "alex@example.com", 2023),
User("2", "Sam", "sam@example.com", 2024),
User("3", "Jordan", "jordan@example.com", 2025),
User("4", "Taylor", "taylor@example.com", 2026),
)
fun getAllUsers(): List<User> = users.toList()
fun getUserById(id: String): User? = users.find { it.id == id }
fun searchUsers(query: String): List<User> {
val lowerQuery = query.lowercase()
return users.filter {
it.name.lowercase().contains(lowerQuery) ||
it.email.lowercase().contains(lowerQuery)
}
}
fun addUser(user: User): Boolean {
if (!user.isValid()) return false
if (users.any { it.email == user.email }) return false
users.add(user)
return true
}
fun deleteUser(id: String): Boolean {
return users.removeAll { it.id == id }
}
fun getUserCount(): Int = users.size
}
Bu repository’nin tamamı (veri modelleri, doğrulama, arama, CRUD işlemleri) paylaşılan koddur. Platformlar arasında sıfır tekrar.
Paylaşılan Kodu Uygulamada Kullanmak
Şimdi bu paylaşılan kodu Compose UI’da kullanalım. composeApp/src/commonMain/kotlin/App.kt dosyasını açın veya oluşturun:
@Composable
fun App() {
val repository = remember { UserRepository() }
var users by remember { mutableStateOf(repository.getAllUsers()) }
var searchQuery by remember { mutableStateOf("") }
MaterialTheme {
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Text(
"Users (${repository.getUserCount()})",
style = MaterialTheme.typography.headlineMedium
)
// Arama çubuğu
OutlinedTextField(
value = searchQuery,
onValueChange = {
searchQuery = it
users = if (it.isEmpty()) repository.getAllUsers()
else repository.searchUsers(it)
},
label = { Text("Search") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
// Kullanıcı listesi
LazyColumn {
items(users) { user ->
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text(user.displayName(), fontWeight = FontWeight.Bold)
Text(user.email, fontSize = 14.sp)
Text(
"Member for ${user.membershipYears()} year(s)",
fontSize = 12.sp,
color = Color.Gray
)
}
}
}
}
}
}
Bu Compose kodu DA paylaşılır, Android, iOS ve Desktop’ta çalışır. UserRepository, User data class’ı, displayName(), membershipYears(): hepsi paylaşılan modülden geliyor.
Bölüm 7: Gradle Yapılandırmasını Anlamak
settings.gradle.kts
// Projede hangi modüllerin var olduğunu bildirir
rootProject.name = "MyKmpApp"
include(":shared") // Paylaşılan Kotlin modülü
include(":composeApp") // Uygulama modülü (Android/iOS/Desktop)
shared/build.gradle.kts
Bu, en önemli derleme dosyası. Hangi platformların hedefleneceğini yapılandırır:
kotlin {
// Android hedefi
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
}
}
// iOS hedefleri: tam uyumluluk için üçü de gerekli
listOf(
iosX64(), // Intel Mac simülatörleri
iosArm64(), // Gerçek iOS cihazları
iosSimulatorArm64() // Apple Silicon Mac simülatörleri
).forEach {
it.binaries.framework {
baseName = "Shared" // iOS framework'ünün adı
isStatic = true
}
}
// Kaynak setleri: bağımlılıkların gittiği yer
sourceSets {
commonMain.dependencies {
// TÜM platformlar için bağımlılıklar
// örneğin kotlinx-coroutines, kotlinx-serialization
}
androidMain.dependencies {
// Sadece Android bağımlılıkları
}
iosMain.dependencies {
// Sadece iOS bağımlılıkları
}
commonTest.dependencies {
// Paylaşılan kod için test bağımlılıkları
implementation(kotlin("test"))
}
}
}
Anahtar kavramlar:
androidTarget(): Android derlemesini etkinleştiririosX64(),iosArm64(),iosSimulatorArm64(): tam cihaz/simülatör kapsaması için üç iOS hedefisourceSets: her platform için bağımlılık bildirdiğiniz yercommonMain‘deki bağımlılıklar otomatik olarak tüm platformlara yayılır
gradle.properties
# Gradle daemon için bellek
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# Kotlin kod stili
kotlin.code.style=official
# Compose Multiplatform'u etkinleştir
kotlin.mpp.applyDefaultHierarchyTemplate=true
Bölüm 8: iOS Kotlin Kodunuzu Nasıl Görür
iOS için derlediğinizde, KMP, paylaşılan Kotlin kodunuzu Shared.framework adında native bir Objective-C framework’üne derler. Swift bu framework’ü doğrudan import edebilir.
Kotlin, Swift’te Neye Dönüşür
| Kotlin | Swift |
|---|---|
data class User(...) | class User |
object Calculator | Calculator.shared (singleton) |
fun greet(): String | func greet() -> String |
suspend fun getUsers() | Asenkron callback (veya sarmalayıcıyla async) |
sealed interface | Protocol + sınıflar |
enum class | KotlinEnum |
List<User> | [User] (NSArray) |
Örnek: Swift’te bir Kotlin object’i:
// Kotlin (shared/commonMain)
object Calculator {
fun add(a: Double, b: Double): Double = a + b
}
// Swift (iosApp)
import Shared
let result = Calculator.shared.add(a: 10.0, b: 5.0)
print(result) // 15.0
.shared, Kotlin object singleton’larının Swift’te nasıl göründüğü. Alışmak birkaç dakika alır, ama sorunsuz çalışır.
Bölüm 9: Test Yazmak ve Çalıştırmak
Paylaşılan kod, paylaşılan testlere sahip olabilir. shared/src/commonTest/kotlin/UserTest.kt dosyasını oluşturun:
package com.ornek.mykmpapp
import com.ornek.mykmpapp.models.User
import com.ornek.mykmpapp.utils.StringUtils
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class UserTest {
@Test
fun validUserShouldReturnTrue() {
val user = User("1", "Alex", "alex@example.com")
assertTrue(user.isValid())
}
@Test
fun invalidEmailShouldReturnFalse() {
val user = User("1", "Alex", "not-an-email")
assertFalse(user.isValid())
}
@Test
fun emptyNameShouldReturnFalse() {
val user = User("1", "", "alex@example.com")
assertFalse(user.isValid())
}
@Test
fun displayNameShouldUseEmailWhenNameIsBlank() {
val user = User("1", "", "alex@example.com")
assertEquals("alex", user.displayName())
}
@Test
fun membershipYearsShouldCalculateCorrectly() {
val user = User("1", "Alex", "alex@example.com", 2024)
assertEquals(2, user.membershipYears())
}
}
class StringUtilsTest {
@Test
fun capitalizeWordsShouldWork() {
assertEquals("Hello World", StringUtils.capitalizeWords("hello world"))
}
@Test
fun truncateShouldAddSuffix() {
assertEquals("Hello...", StringUtils.truncate("Hello World", 8))
}
@Test
fun isValidEmailShouldWork() {
assertTrue(StringUtils.isValidEmail("alex@example.com"))
assertFalse(StringUtils.isValidEmail("not-email"))
assertFalse(StringUtils.isValidEmail("@example.com"))
}
@Test
fun slugifyShouldWork() {
assertEquals("hello-world", StringUtils.slugify("Hello World!"))
}
}
Testleri çalıştırın:
# Tüm platformlar için testleri çalıştır
./gradlew :shared:allTests
# Sadece Android için testleri çalıştır
./gradlew :shared:testDebugUnitTest
# Sadece iOS için testleri çalıştır
./gradlew :shared:iosSimulatorArm64Test
Bu testler hem Android’de hem iOS’ta çalışır, aynı test kodu, paylaşılan mantığın her platformda doğru çalıştığını doğrular.
Türkçe Dokümantasyon Eksikliği: Bu Sizi Nasıl Etkiler
KMP ile çalışırken karşılaşacağınız pratik bir gerçek şu: JetBrains’in resmi dokümantasyonu, topluluk forumları (Kotlin Slack, Stack Overflow) ve neredeyse tüm hata mesajı çözümleri İngilizce. Türkçe kaynaklı KMP eğitim içeriği hâlâ çok az, bu yazı gibi rehberler dışında Android geliştiricilerin çoğu doğrudan resmi İngilizce dokümantasyona veya İngilizce YouTube içeriğine yönelmek zorunda kalıyor. Bunun pratik bir sonucu var: kdoctor gibi bir araç bir hata verdiğinde ya da Gradle senkronizasyonu tuhaf bir mesajla başarısız olduğunda, hata mesajını doğrudan İngilizce olarak arama motoruna yapıştırmak, Türkçe bir karşılığını aramaktan çok daha hızlı sonuç veriyor. Ekibinizde İngilizce teknik dokümantasyon okumakta zorlanan geliştiriciler varsa, KMP’ye geçiş kararı verirken bunu bir öğrenme eğrisi maliyeti olarak hesaba katmakta fayda var, çünkü resmi kaynakların Türkçe çevirisi kısa vadede gelmeyecek gibi görünüyor.
Sık Yapılan Hatalar
Hata 1: KMP Eklentisini Unutmak
Android Studio’ya Kotlin Multiplatform eklentisini kurmazsanız şunları göremezsiniz:
- iOS çalıştırma yapılandırmaları
- KMP proje şablonları
- Kaynak setleri arasında düzgün kod gezinimi
Çözüm: Settings → Plugins → “Kotlin Multiplatform” ara → Kur.
Hata 2: commonMain’de Android API’larını Kullanmak
// KÖTÜ: bu iOS'ta çöker çünkü Android API'ları orada yok
// shared/src/commonMain/kotlin/
import android.util.Log // Bu iOS için derlenmez!
fun logMessage(msg: String) {
Log.d("TAG", msg) // Sadece Android API'sı
}
// İYİ: platforma özgü API'lar için expect/actual kullan
// shared/src/commonMain/kotlin/
expect fun logMessage(msg: String)
// shared/src/androidMain/kotlin/
actual fun logMessage(msg: String) {
android.util.Log.d("TAG", msg)
}
// shared/src/iosMain/kotlin/
actual fun logMessage(msg: String) {
platform.Foundation.NSLog(msg)
}
Hata 3: Kaynak Seti Görünürlüğünü Anlamamak
commonMain şunu görebilir: sadece commonMain
androidMain şunu görebilir: commonMain + androidMain
iosMain şunu görebilir: commonMain + iosMain
commonMain ŞUNU GÖREMEZ: androidMain veya iosMain
commonMain’de Android kodu kullanmaya çalışırsanız derlenmez. Aralarında köprü kurmak için expect/actual kullanın.
Hata 4: Büyük İlk Gradle Senkronizasyonu
İlk senkronizasyon yaklaşık 500 MB bağımlılık indirir (Kotlin/Native derleyicisi, iOS araç zincirleri vb.). Paniğe kapılmayın. İyi bir internet bağlantısı kullanın ve bekleyin.
Hata 5: iOS Framework’ünü Derlememek
Xcode paylaşılan kodunuzu bulamıyorsa:
# Framework'ü manuel derle
./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
Bu, Xcode’un ihtiyaç duyduğu Shared.framework‘ü üretir.
Hızlı Referans
| İşlem | Komut |
|---|---|
| Android’i derle | ./gradlew :composeApp:assembleDebug |
| iOS framework’ünü derle | ./gradlew :shared:linkDebugFrameworkIosSimulatorArm64 |
| Testleri çalıştır (tümü) | ./gradlew :shared:allTests |
| Testleri çalıştır (Android) | ./gradlew :shared:testDebugUnitTest |
| Desktop uygulamasını çalıştır | ./gradlew :composeApp:run |
| Temiz derleme | ./gradlew clean |
| Ortamı kontrol et | kdoctor |