Swift'in modern concurrency sistemi, asenkron kod yazmayı güvenli ve okunabilir hale getiriyor.
İçindekiler
- Concurrency Yaklasimlari Karsilastirmasi
- Async/Await Temelleri
- Task ve Task Groups
- Actors ve Data Isolation
- MainActor ve UI Updates
- Task Cancellation
- AsyncSequence ve AsyncStream
- Error Handling
- Best Practices
- Sonuç
Swift Concurrency Yaklasimlari Karsilastirmasi
Yaklasim | Thread Safety | Okunabilirlik | Performans | iOS Minimum | Onerilen Kullanim |
|---|---|---|---|---|---|
**GCD (DispatchQueue)** | Manuel | Dusuk | Iyi | iOS 4+ | Legacy projeler |
**OperationQueue** | Manuel | Orta | Iyi | iOS 4+ | Karmasik is akislari |
**Combine** | Otomatik | Orta | Iyi | iOS 13+ | Reactive streams |
**async/await** | Otomatik | Yuksek | Cok iyi | iOS 13+ | Genel asenkron isler |
**Actor** | Otomatik | Yuksek | Iyi | iOS 13+ | Shared mutable state |
**TaskGroup** | Otomatik | Yuksek | Cok iyi | iOS 13+ | Paralel islemler |
**AsyncSequence** | Otomatik | Yuksek | Iyi | iOS 13+ | Streaming veri |
Yeni projelerde async/await ve Actor tercih edin. GCD sadece cok dusuk seviye performans gereksinimleri icin kullanilmalidir.
Async/Await Temelleri
swift
1// Async function tanımı2func fetchUser(id: UUID) async throws -> User {3 let url = URL(string: "https://api.example.com/users/\(id)")!4 let (data, response) = try await URLSession.shared.data(from: url)5 6 guard let httpResponse = response as? HTTPURLResponse,7 httpResponse.statusCode == 200 else {8 throw NetworkError.invalidResponse9 }10 11 return try JSONDecoder().decode(User.self, from: data)12}13 14// Çağırma15Task {16 do {17 let user = try await fetchUser(id: userId)18 print("User: \(user.name)")19 } catch {20 print("Error: \(error)")21 }22}Task ve Task Groups
swift
1// Serial execution2func loadUserData(userId: UUID) async throws -> UserProfile {3 let user = try await fetchUser(id: userId)4 let posts = try await fetchPosts(for: userId)5 let followers = try await fetchFollowers(for: userId)6 7 return UserProfile(user: user, posts: posts, followers: followers)8}9 10// Parallel execution with async let11func loadUserDataParallel(userId: UUID) async throws -> UserProfile {12 async let user = fetchUser(id: userId)13 async let posts = fetchPosts(for: userId)14 async let followers = fetchFollowers(for: userId)15 16 return try await UserProfile(17 user: user,18 posts: posts,19 followers: followers20 )21}22 23// TaskGroup for dynamic parallelism24func fetchAllUsers(ids: [UUID]) async throws -> [User] {25 try await withThrowingTaskGroup(of: User.self) { group in26 for id in ids {27 group.addTask {28 try await fetchUser(id: id)29 }30 }31 32 var users: [User] = []33 for try await user in group {34 users.append(user)35 }36 return users37 }38}39 40// TaskGroup with rate limiting41func fetchWithRateLimit(ids: [UUID], maxConcurrent: Int = 5) async throws -> [User] {42 try await withThrowingTaskGroup(of: User.self) { group in43 var iterator = ids.makeIterator()44 var users: [User] = []45 46 // Start initial batch47 for _ in 0..<min(maxConcurrent, ids.count) {48 if let id = iterator.next() {49 group.addTask { try await fetchUser(id: id) }50 }51 }52 53 // Process results and add new tasks54 for try await user in group {55 users.append(user)56 57 if let id = iterator.next() {58 group.addTask { try await fetchUser(id: id) }59 }60 }61 62 return users63 }64}Actors ve Data Isolation
swift
1// Actor for thread-safe state2actor ImageCache {3 private var cache: [URL: UIImage] = [:]4 private var inProgress: [URL: Task<UIImage, Error>] = [:]5 6 func image(for url: URL) async throws -> UIImage {7 // Return cached image8 if let cached = cache[url] {9 return cached10 }11 12 // Return in-progress task13 if let task = inProgress[url] {14 return try await task.value15 }16 17 // Start new download18 let task = Task {19 let (data, _) = try await URLSession.shared.data(from: url)20 guard let image = UIImage(data: data) else {21 throw ImageError.invalidData22 }23 return image24 }25 26 inProgress[url] = task27 28 do {29 let image = try await task.value30 cache[url] = image31 inProgress[url] = nil32 return image33 } catch {34 inProgress[url] = nil35 throw error36 }37 }38 39 func clearCache() {40 cache.removeAll()41 }42}43 44// Global actor45@globalActor46actor DatabaseActor {47 static let shared = DatabaseActor()48}49 50@DatabaseActor51class DatabaseManager {52 func save(_ entity: Entity) async {53 // Database operations54 }55}MainActor ve UI Updates
swift
1@MainActor2class ProfileViewModel: ObservableObject {3 @Published private(set) var user: User?4 @Published private(set) var isLoading = false5 @Published private(set) var error: Error?6 7 private let repository: UserRepositoryProtocol8 9 init(repository: UserRepositoryProtocol) {10 self.repository = repository11 }12 13 func loadUser(id: UUID) async {14 isLoading = true15 defer { isLoading = false }16 17 do {18 user = try await repository.fetchUser(id: id)19 } catch {20 self.error = error21 }22 }23}24 25// Explicit MainActor usage26func updateUI(with data: Data) {27 Task { @MainActor in28 label.text = String(data: data, encoding: .utf8)29 }30}31 32// MainActor.run33func processAndDisplay() async {34 let result = await heavyComputation()35 36 await MainActor.run {37 displayResult(result)38 }39}Task Cancellation
swift
1class SearchViewModel: ObservableObject {2 @Published var searchText = ""3 @Published private(set) var results: [SearchResult] = []4 5 private var searchTask: Task<Void, Never>?6 7 func search() {8 // Cancel previous search9 searchTask?.cancel()10 11 searchTask = Task {12 // Debounce13 try? await Task.sleep(nanoseconds: 300_000_000)14 15 // Check cancellation16 guard !Task.isCancelled else { return }17 18 do {19 let results = try await performSearch(query: searchText)20 21 // Check again before UI update22 guard !Task.isCancelled else { return }23 24 await MainActor.run {25 self.results = results26 }27 } catch {28 if !(error is CancellationError) {29 print("Search error: \(error)")30 }31 }32 }33 }34}35 36// Cooperative cancellation in loops37func processItems(_ items: [Item]) async throws {38 for item in items {39 try Task.checkCancellation()40 await process(item)41 }42}AsyncSequence ve AsyncStream
swift
1// AsyncSequence for paginated data2struct PaginatedProducts: AsyncSequence {3 typealias Element = [Product]4 5 let pageSize: Int6 7 struct AsyncIterator: AsyncIteratorProtocol {8 var currentPage = 09 let pageSize: Int10 var hasMore = true11 12 mutating func next() async throws -> [Product]? {13 guard hasMore else { return nil }14 15 let products = try await fetchProducts(page: currentPage, size: pageSize)16 currentPage += 117 hasMore = products.count == pageSize18 19 return products.isEmpty ? nil : products20 }21 }22 23 func makeAsyncIterator() -> AsyncIterator {24 AsyncIterator(pageSize: pageSize)25 }26}27 28// Usage29for try await page in PaginatedProducts(pageSize: 20) {30 displayProducts(page)31}32 33// AsyncStream for events34func locationUpdates() -> AsyncStream<CLLocation> {35 AsyncStream { continuation in36 let manager = CLLocationManager()37 let delegate = LocationDelegate { location in38 continuation.yield(location)39 }40 41 manager.delegate = delegate42 manager.startUpdatingLocation()43 44 continuation.onTermination = { _ in45 manager.stopUpdatingLocation()46 }47 }48}Error Handling
swift
1// Typed errors (Swift 6.0)2enum DataError: Error {3 case notFound4 case networkError(underlying: Error)5 case decodingFailed6}7 8func fetchData() async throws(DataError) -> Data {9 do {10 let (data, _) = try await URLSession.shared.data(from: url)11 return data12 } catch let error as URLError {13 throw .networkError(underlying: error)14 } catch {15 throw .notFound16 }17}18 19// Result-based approach20func safeFetch() async -> Result<Data, DataError> {21 do {22 let data = try await fetchData()23 return .success(data)24 } catch {25 return .failure(error as! DataError)26 }27}Best Practices
- Structured concurrency kullanın: Task grupları ile lifecycle yönetimi
- Cancellation'ı handle edin: Her async işlemde cancellation kontrolü
- MainActor'ı doğru kullanın: Sadece UI güncellemeleri için
- Actor'ları tercih edin: Shared mutable state için
- async let ile parallelizm: Bağımsız işlemler için
Sonuç
Swift concurrency, güvenli ve performanslı asenkron kod yazmayı kolaylaştırır. async/await, actors ve structured concurrency patterns ile race condition'lardan arınmış kod yazabilirsiniz.
Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
Okuyucu Ödülü
Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:
ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.

