İçeriğe geç

Uygulamımı Swift 6'ya Hazırlamak

Xcode projelerin ve SwiftPM modüllerin için bugünden Swift 6 modunu nasıl etkinleştireceğini ve geçiş deneyiminin nasıl olduğunu anlatıyorum.

Uygulamımı Swift 6'ya Hazırlamak

“Swift 6 modu” nedir?

Swift 6, 2023’te yayınlanmayacak — bu, Swift Language Workgroup’tan Doug Gregor tarafından netleştirildi. Ama Apple’ın Swift 6’nın bazı kısımlarını zaten 5.8’de gönderdiğini biliyor muydun? Evet, doğru. Birkaç hafta önce Xcode 14.3 ile gelen Swift’in bazı kısımları varsayılan olarak kapalı. Swift 6 çıktığında açılacaklar — bu bir yıl daha sürebilir, hatta daha da uzun.

Bu özellikler Swift’e bazı kırıcı değişiklikler getiriyor, örneğin bilinen API’leri yeniden adlandırarak, davranışlarını ayarlayarak veya derleyiciye yeni güvenlik kontrolleri ekleyerek. Ama hepsi eninde sonunda açılacak ve kod tabanlarımızı iyileştirmeye yardımcı olacak. Ve projelerimizi bu değişikliklerle uyumlu çalışacak şekilde güncellememiz gerekecek.

Projelerimde tüm özellikleri açarak, kod tabanım için bilmem gereken herhangi bir kırıcı değişiklik olup olmadığını görmenin iyi bir fikir olacağını düşündüm. Ve tabii ki bazı yeni özelliklerden de faydalanabilirdim, mesela BareSlashRegexLiterals — kısa Regex başlatma için /.../ regex literal sözdizimini kullanılabilir kılan özellik.

Neyse ki Swift 5.8 ile bu seçenekleri etkinleştirmenin artık birleşik bir yolu var: Swift’e -enable-upcoming-feature geçirmemiz yeterli, bunu Xcode’daki proje derleme ayarlarında OTHER_SWIFT_FLAGS alanına ekleyerek yapıyoruz. Ama hangi özelliklerin mevcut olduğunu da bilmemiz gerekiyor ve iyi bir genel bakış sunan bir yer bulamadım (henüz). Bu birleşik seçeneği tanıtan öneri böyle bir liste içeriyor, ama SE-0384’ten gelen gibi daha sonra eklenen seçeneklerle güncellenmedi. Peki, şu anda desteklenen tüm seçeneklerin güvenilir bir listesini nereden bulabiliriz?

✨ GUNCELLEME: Artik yakinda gelecek bayraklara gore filtreleme dogrudan Swift.org’da yapilabiliyor.

Swift acik kaynak, bu yuzden en guvenilir yer Swift GitHub deposu! release/5.8 branch’inde UPCOMING_FEATURE adli girisler iceren bir Features.def dosyasi var, hem ilgili Swift Evolution oneri numarasini hem de acilacaklari Swift surumunu iceriyor:

UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
UPCOMING_FEATURE(ForwardTrailingClosures, 286, 6)
UPCOMING_FEATURE(BareSlashRegexLiterals, 354, 6)
UPCOMING_FEATURE(ExistentialAny, 335, 6)

Secenekler ve ne yaptiklarina dair kisa aciklamalar:

Nedense iki secenek orada listelenmemis gorunuyor (arastiriyorum):

Sonraki surumlerle daha fazla secenek gelecek, ornegin ImportObjcForwardDeclarations.

Kodumu uygun concurrency destegi acisindan kontrol etmek icin -warn-concurrency (bu aslinda StrictConcurrency calisiyorsa ayni sey olmali) ve -enable-actor-data-race-checks de gecirmeyi sectim.

Projemi Tasimak

Sen de benim gibi projende tum 5.8 seceneklerini etkinlestirmek istiyorsan, asagidaki metin blogunu kopyala (C), sonra Xcode projenin “Build Settings” sekmesine git, “Other Swift Flags” secenegini bul, editorde sec ve yapistir (V):

//:configuration = Debug
OTHER_SWIFT_FLAGS = -enable-upcoming-feature BareSlashRegexLiterals -enable-upcoming-feature ConciseMagicFile -enable-upcoming-feature ExistentialAny -enable-upcoming-feature ForwardTrailingClosures -enable-upcoming-feature ImplicitOpenExistentials -enable-upcoming-feature StrictConcurrency -warn-concurrency -enable-actor-data-race-checks

//:configuration = Release
OTHER_SWIFT_FLAGS = -enable-upcoming-feature BareSlashRegexLiterals -enable-upcoming-feature ConciseMagicFile -enable-upcoming-feature ExistentialAny -enable-upcoming-feature ForwardTrailingClosures -enable-upcoming-feature ImplicitOpenExistentials -enable-upcoming-feature StrictConcurrency -warn-concurrency -enable-actor-data-race-checks

//:completeSettings = some
OTHER_SWIFT_FLAGS

.enableUpcomingFeature is only available from Swift 5.8

Benim gibi SwiftPM ile modulerlesmis bir uygulama kullaniyorsan veya bir Swift paketi uzerinde calisiyorsan, ek olarak her hedefin swiftSettings uzerinden .enableUpcomingFeature dizisi gecirmen gerekecek:

let swiftSettings: [SwiftSetting] = [
   .enableUpcomingFeature("BareSlashRegexLiterals"),
   .enableUpcomingFeature("ConciseMagicFile"),
   .enableUpcomingFeature("ExistentialAny"),
   .enableUpcomingFeature("ForwardTrailingClosures"),
   .enableUpcomingFeature("ImplicitOpenExistentials"),
   .enableUpcomingFeature("StrictConcurrency"),
   .unsafeFlags(["-warn-concurrency", "-enable-actor-data-race-checks"]),
]

let package = Package(
   // ...
   targets: [
      // ...
      .target(
         name: "MyTarget",
         dependencies: [/* ... */],
         swiftSettings: swiftSettings
      ),
      // ...
   ]

Dosyanin en ustundeki tools version’i 5.8’e yukseltmeyi unutma:

// swift-tools-version:5.8

.enableUpcomingFeature yalnizca Swift 5.8’den itibaren mevcut

Bunun nedeni Swift’in, proje hedefin icin belirttigin secenekleri, projene import ettigin modullere otomatik olarak aktarmamasi. Ve bu iyi bir haber, cunku bu sayede projene dahil ettigin Swift paketlerinin herhangi bir ayarlama yapmasina gerek kalmaz ve sen yine de kendi uygulama kodun icin bu ozellikleri kullanabilirsin. Tersi de gecerli: Paket yazarlari bu ozellikleri kendi projeleri icin acabilir ve tuketildikleri projelerdeki kodu etkilemez.

Bunlari actiktan ve derledikten sonra dort tur sorunla karsilastim:

  1. Bircok yerde any anahtar kelimesini eklemem gerekti — Xcode Fix-It ile yardim etti:

Migrating my project

Migrating my project 2

  1. Nedense .sheet modifier’i olan view’larda cok sayida hata aldim. Hata ciftleri sunu belirtiyordu: “Generic parameter ‘Content’ could not be inferred” ve “Missing argument for parameter ‘content’ in call”. Bu mesajlar cok yardimci degildi, bu yuzden once .sheet icerigini sadece bir Text view ile degistirmeyi denedim ama yardimci olmadi. Sonra secenekleri tek tek kapatmayi denedim ve ForwardTrailingClosures‘i kapattigimda hatalar kayboldu, bu yuzden kapali tuttum. Swift’in gelecek surumlerinde daha sonra duzeltmek icin daha iyi bir hata mesaji uretilecegini umuyorum. Acele yok, sonucta. Swift 5.9’da tekrar deneyebilirim. Simdi arastirmaya vaktim olmadi.

Migrating my project 3

  1. TCA WithViewStore donduren bazi fonksiyonlarimi @MainActor ozniteligi ile isaretlemem gerekti, ama yine Xcode Fix-It’lerle yardim etti.

Migrating my project 4

  1. Bircok yerde “Non-sendable type ‘…’ passed in call to main actor-isolated function cannot cross actor boundary” uyarilari gosterildi. Bu yuzden bu turleri Sendable protokolune uyumlu hale getirdim (Sendable hakkinda burada bilgi edin).

Diger her sey ~35 bin satir Swift kodu olan RemafoX uygulamam icin sorunsuz derlendi. Tum surec 3 saatten az zamanimmi aldi.

Projem artik Swift’in gelecegine hazir ve yeni Regex literal ozelligini kullanabiliyorum (let regex = /.*@.*/). Ayrica, daha sonra Swift 6’ya tasimam gerekecek yeni kod yazamiyorum cunku aninda hata aliyorum.

Peki senin projen? Hangi yakinda gelecek ozelliklere gecis yapmak istiyorsun?

Bu yazıyı beğendin mi? Swift ipuçları ve indie geliştirici güncellemeleri için Bluesky ve Mastodon üzerinden takip et.