# Swift Concurrency Cheat Sheet

Swift 5.5+ versiyasidan boshlab joriy qilingan zamonaviy asinxron dasturlash modeli: `async/await`, `Task`, `Actor` va `Structured Concurrency` bo'yicha tezkor qo'llanma.

---

## 1. async / await Asoslari

```swift
// Asinxron funksiya e'lon qilish
func fetchUser(id: String) async throws -> User {
    let url = URL(string: "https://api.example.com/users/\(id)")!
    let (data, response) = try await URLSession.shared.data(from: url)
    
    guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
        throw NetworkError.badServerResponse
    }
    return try JSONDecoder().decode(User.self, from: data)
}

// Chaqirish
Task {
    do {
        let user = try await fetchUser(id: "101")
        print("Foydalanuvchi:", user.name)
    } catch {
        print("Xatolik:", error)
    }
}
```

---

## 2. Task va Bekor Qilish (Task & Cancellation)

```swift
// 1. Yangi Task yaratish (Ota kontekstning actor va prioritetini meros oladi)
let task = Task(priority: .userInitiated) {
    for i in 1...100 {
        // Har qadamda bekor qilinganini tekshirish:
        try Task.checkCancellation()
        
        // Yoki if orqali:
        if Task.isCancelled { break }
        
        // 1 soniya kutish (thread bloklanmaydi)
        try await Task.sleep(nanoseconds: 1_000_000_000)
        print("Qadam \(i)")
    }
}

// Taskni to'xtatish
task.cancel()

// 2. Detached Task (Kontekstdan butunlay ajralgan yangi mustaqil task)
Task.detached(priority: .background) {
    await performHeavyCalculation()
}
```

---

## 3. Structured Concurrency: `async let` va `TaskGroup`

### `async let` — Bir nechta so'rovni parallel bajarish:
```swift
func loadDashboardData() async throws -> (Profile, Feed, [Notification]) {
    // Har biri bir vaqtda parallel ishga tushadi
    async let userProfile = fetchProfile()
    async let userFeed = fetchFeed()
    async let notifications = fetchNotifications()

    // Barchasining natijasi tayyor bo'lguncha kutadi
    return try await (userProfile, userFeed, notifications)
}
```

### `TaskGroup` — Dinamik miqdordagi parallel vazifalar:
```swift
func downloadImages(urls: [URL]) async throws -> [UIImage] {
    try await withThrowingTaskGroup(of: UIImage.self) { group in
        for url in urls {
            group.addTask {
                let (data, _) = try await URLSession.shared.data(from: url)
                guard let image = UIImage(data: data) else {
                    throw ImageError.corruptData
                }
                return image
            }
        }

        var images: [UIImage] = []
        for try await image in group {
            images.append(image)
        }
        return images
    }
}
```

---

## 4. Actors & Data Isolation (Thread Safety)

`actor` reference type bo'lib, o'zining ichki holatini data race'lardan (bir vaqtda bir nechta threaddan o'qish/yozish) avtomatik himoyalaydi.

```swift
actor BankAccount {
    private var balance: Double = 0.0

    func deposit(amount: Double) {
        balance += amount
    }

    func withdraw(amount: Double) -> Bool {
        guard balance >= amount else { return false }
        balance -= amount
        return true
    }

    // Actor ichida data race xavfi bo'lmagan konstantalar uchun:
    nonisolated let accountNumber = "123-456"
}

// Ishlatish: tashqaridan chaqirganda har doim 'await' qo'yiladi
let account = BankAccount()
await account.deposit(amount: 50.0)
let success = await account.withdraw(amount: 20.0)
```

---

## 5. `@MainActor`

UI bilan bog'liq barcha amallar Main Thread'da bajarilishini kafolatlaydi.

```swift
@MainActor
final class ProfileViewModel: ObservableObject {
    @Published var username: String = ""

    func loadProfile() async {
        // Tarmoq so'rovi background threadda bajariladi
        let name = await NetworkService.shared.getName()
        // Bu qator avtomatik Main Threadda ishlaydi
        self.username = name
    }
}

// Istalgan joydan Main Threadga o'tish:
await MainActor.run {
    view.backgroundColor = .systemGreen
}
```

---

## 6. `Sendable` va `@Sendable`

Concurrency kontekstlari (threadlar va tasklar) o'rtasida xavfsiz uzatilishi mumkin bo'lgan turlar `Sendable` protokoliga to'g'ri keladi.

- **Avtomatik Sendable**: Value type'lar (`struct`, `enum`), oddiy turlar (`Int`, `String`), va `actor`.
- **Class'lar**: Faqat `final` bo'lsa va faqat `let` (o'zgarmas) `Sendable` xususiyatlarga ega bo'lsagina Sendable bo'la oladi.

```swift
// Sendable Struct
struct UserDTO: Sendable {
    let id: String
    let email: String
}

// @Sendable Closure
func executeInBackground(work: @Sendable @escaping () -> Void) {
    Task.detached {
        work()
    }
}
```

---

## 7. `AsyncStream` (Asinxron Oqimlar)

Callback yoki NotificationCenter asosidagi eski API'larni zamonaviy `for await` oqimiga aylantirish:

```swift
func locationUpdates() -> AsyncStream<CLLocation> {
    AsyncStream { continuation in
        let manager = LocationManagerHelper()
        manager.onUpdate = { location in
            continuation.yield(location) // Yangi element chiqarish
        }
        manager.onError = {
            continuation.finish() // Oqimni tugatish
        }
        continuation.onTermination = { _ in
            manager.stopUpdating()
        }
    }
}

// Ishlatilishi:
Task {
    for await location in locationUpdates() {
        print("Yangi koordinata:", location.coordinate)
    }
}
```

---

## 8. GCD (Eski) vs Swift Concurrency (Yangi) Taqqoslash

| Eski usul (Grand Central Dispatch) | Yangi usul (Swift Concurrency) |
|---|---|
| `DispatchQueue.main.async { ... }` | `@MainActor` yoki `await MainActor.run { ... }` |
| `DispatchQueue.global().async { ... }` | `Task { ... }` yoki `Task.detached { ... }` |
| `DispatchGroup` (`enter()`, `leave()`) | `async let` yoki `withTaskGroup` |
| `Thread.sleep(forTimeInterval: 1.0)` | `try await Task.sleep(nanoseconds: 1_000_000_000)` |
| `completionHandler: @escaping (Result<T, Error>) -> Void` | `func doWork() async throws -> T` |
| `NSLock` / `os_unfair_lock` / Serial Queue | `actor` |
