Swift'in async/await yapısı ve yeni concurrency modelini kavramakta takıldığım noktalar var. Özellikle görev (Task) yönetimi, aktör (actor) kullanımı ve main thread ile senkronizasyon arasındaki farkları tam olarak nasıl modelleyebileceğimiz merak ediyorum. Ayrıca Combine ile async/await arasında geçiş yaparken hangi yaklaşımlar daha sürdürülebilir? Siz bu konularda hangi kaynakları önerirsiniz, pratikte hangi örnekler üzerinden ilerlemek daha faydalı olur? Birlikte bir mini proje yapıp deneyimlerimizi paylaşabilir miyiz? Görüşlerinizi duymak için sabırsızlanıyorum.
Swift'te async/await ve Concurrency temelleri hakkında ne biliyorsunuz?
👁️ 36 görüntüleme💬 2 cevap❤️ 0 beğeni
2 Cevap
Geçen ay bir iOS uygulaması geliştirirken async/await’a geçiş yaptım, işin en çetrefilli kısmı da görev (Task) yönetimi ve aktör (actor) idi. Başlangıçta UI‑yi güncellerken “MainActor.run” kullanmayı unutmuşum, bu yüzden bir iki kez “UIKit has to be used on the main thread” hatası alıyordum. Valla, sorunu çözmek için tüm UI‑bağlantılı kodu `@MainActor` ile işaretlemek yeterli oldu; böylece Task içinde de main thread’e otomatik geçiş sağlandı. Aktörler ise veri yarışını engellemek için harika; ben bir `DataCache` aktörü oluşturdum ve içinde `fetch` metodunu `nonisolated` olarak bırakıp sadece okuma‑yazma işlemlerini aktör içinde tutarak race condition’ları tamamen ortadan kaldırdım.
Combine’dan async/await’a geçişte ise en çok “Future”ları `await` ile sarmak yerine, `AsyncThrowingStream` ya da `AsyncSequence` kullanmak daha temiz bir yol oldu. Özellikle bir API çağrısını `URLSession.shared.data(for:)` ile async yapıya taşıdıktan sonra, Combine zincirini tamamen kaldırıp sadece `await` ile beklemek kodu %30 kadar sadeleştirdi. Başlangıçta “Swift Concurrency” kitabı ve Apple’ın “Concurrency in Swift” WWDC videosu işime çok yaradı; bir de “Swift by Sundell” blogunda actor örnekleri var, onları incelemenizi tavsiye ederim. Mini proje fikri güzel; bir “Todo” listesi yapıp veri senkronizasyonunu aktörle, UI güncellemelerini @MainActor ile, eski Combine akışlarını da async/await’a çevirerek birlikte test edebiliriz. Ne dersin kanka, bir repo açıp adım adım ilerleyelim?
Async/await’i Swift’te kullandığımda en çok takıldığım nokta, `Task`’ların yaşam döngüsünü kontrol etmek oldu. Valla, bir `Task` başlatıp sonra UI’da bir hata çıkınca onu iptal etmek zorunda kalınca, `Task { @MainActor in … }` ya da `task.cancel()`’ı nerede çağıracağımız konusunda kafa karıştı. Bence en pratik yol, view‑model içinde bir `@MainActor` fonksiyon tanımlayıp, oradan `Task { await fetchData() }` demek; böylece UI‑thread’e otomatik geçiş sağlanıyor ve iptal mantığı da aynı scope içinde kalıyor. Actor’lar ise veri yarışını önlemek için süper, ama gerçek hayatta birden çok `Task` aynı actor’a istek attığında sıraya giriyor; bu da bazen istenmeyen gecikmelere yol açabiliyor. Ben genelde “state” sınıflarını actor içine koyup, sadece `await` ile erişiyorum; UI’da değişiklik yapmam gerektiğinde de `@MainActor` köprü fonksiyonu kullanıyorum.
Combine’dan async/await’a geçişte ise `AsyncSequence` ve `AsyncStream` en çok işime yaradı. Örneğin bir `PassthroughSubject` yerine:
```swift
func streamValues() -> AsyncStream<Int> {
AsyncStream { continuation in
let cancellable = publisher.sink { value in
continuation.yield(value)
}
continuation.onTermination = { _ in cancellable.cancel() }
}
}
```
şeklinde bir adapter yazarak, eski pipeline’ı korurken yeni `for await` döngüsüyle tüketebiliyorsunuz. Bu yaklaşım kodun sürdürülebilirliğini artırıyor çünkü bir tarafta Combine kalıyor, diğer tarafta async/await akışı; ikisini birden yönetmek zorunda kalmıyorsunuz.
Kaynak olarak, Apple’ın “Concurrency Programming Guide”ı ve Swift.org’da yayımlanan “Swift Concurrency in Practice” makalesini tavsiye ederim. Ayrıca “Swift by Sundell” blogunda async/await ve actor örnekleri çok anlatılmış, özellikle `@MainActor` ile UI senkronizasyonu bölümü benim için altın değerindeydi. Mini proje önerisi: basit bir “Todo” uygulaması yapalım, veri kaynağını Combine‑Publisher’dan async‑await‑based bir servisle değiştirip, actor‑tabanlı bir `TodoStore` yazalım. Böylece hem iptal, hem thread‑safety, hem de UI‑update akışını bir arada görebiliriz. Kanka, bir repo açıp pull request atarsak, birbirimizin kodunu inceleyip daha iyi pratikler çıkarabiliriz.