# 13. Apple Native: Coordinator va Router Pattern

> "Agar sizning ViewController'ingiz boshqa bir ViewController'ni qanday yaratishni va unga qanday o'tishni o'zi hal qilayotgan bo'lsa — siz navigatsiya botqog'idasiz. Coordinator ViewController'ni navigatsiya mas'uliyatidan 100% ozod qiladi."

---

## 1. Massive View Controller (MVC) va Qattiq Bog'liqlik Fojiasi

Klassik iOS loyihalarida eng ko'p uchraydigan xato:

```swift
// ❌ QATTIQ BOG'LIQLIK (TIGHT COUPLING):
class ProductListViewController: UIViewController {
    func didSelectProduct(product: Product) {
        // ProductListViewController boshqa ekranning ichki parametrlarini
        // va navigatsiyani bilishga majbur bo'lmoqda!
        let detailVC = ProductDetailViewController(productId: product.id)
        detailVC.discountCode = "SPRING2026"
        self.navigationController?.pushViewController(detailVC, animated: true)
    }
}
```

### Nega bu halokatli?
1. `ProductListViewController` ni boshqa joyda (masalan, qidiruv natijalarida) qayta ishlatib bo'lmaydi, chunki u `ProductDetailViewController` ga qattiq bog'langan.
2. Push-Notification orqali to'g'ridan-to'g'ri `ProductDetail` ni ochish kerak bo'lsa, butun navigatsiya logikasini boshidan qayta yozish kerak.
3. Unit Testlarda navigatsiya sodir bo'lganini tekshirib bo'lmaydi.

---

## 2. Coordinator Pattern Arxitekturasi

2015-yilda Soroush Khanlou tomonidan taqdim etilgan **Coordinator** patterni butun navigatsiyani alohida obyektga topshiradi:

```mermaid
graph TD
    AppCoord["AppCoordinator (Ilova Asosiy Koordinatori)"] --> AuthCoord["AuthCoordinator (Kirish / Ro'yxatdan O'tish)"]
    AppCoord --> MainTabCoord["MainTabCoordinator (Asosiy Sahifalar)"]

    MainTabCoord --> HomeCoord["HomeCoordinator"]
    MainTabCoord --> OrdersCoord["OrdersCoordinator"]
    MainTabCoord --> ProfileCoord["ProfileCoordinator"]

    OrdersCoord --> OrderListVC["OrdersListViewController\n(Faqat UI chizadi)"]
    OrdersCoord --> OrderDetailVC["OrderDetailViewController\n(Faqat UI chizadi)"]

    style AppCoord fill:#131720,stroke:#bef264,stroke-width:2px
    style OrdersCoord fill:#181d26,stroke:#7da2ce,stroke-width:1px
    style OrderListVC fill:#181d26,stroke:#60a5fa,stroke-width:1px
```

**Qoida:** ViewController faqat bir narsani biladi: "Foydalanuvchi tugmani bosdi". Qayerga o'tishni esa faqat **Coordinator** hal qiladi!

---

## 3. Real Swift 6 Kodi: Universal Coordinator

```swift
import UIKit

// 1. Asosiy Koordinator Protokoli
@MainActor
public protocol Coordinator: AnyObject {
    var childCoordinators: [any Coordinator] { get set }
    var navigationController: UINavigationController { get set }
    func start()
}

// 2. Buyurtmalar Koordinatori
@MainActor
public final class OrdersCoordinator: Coordinator {
    public var childCoordinators: [any Coordinator] = []
    public var navigationController: UINavigationController
    
    public init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    public func start() {
        let listVC = OrdersListViewController()
        // ViewController koordinatorga xabar berishi uchun closure yoki delegat
        listVC.onOrderSelected = { [weak self] orderId in
            self?.showOrderDetail(orderId: orderId)
        }
        navigationController.pushViewController(listVC, animated: true)
    }
    
    public func showOrderDetail(orderId: String) {
        let detailVC = OrderDetailViewController(orderId: orderId)
        detailVC.onPaymentRequested = { [weak self] orderId in
            self?.startPaymentFlow(orderId: orderId)
        }
        navigationController.pushViewController(detailVC, animated: true)
    }
    
    private func startPaymentFlow(orderId: String) {
        // Yangi Child Coordinator (Modal to'lov oqimi)
        let paymentNav = UINavigationController()
        let paymentCoord = PaymentCoordinator(navigationController: paymentNav, orderId: orderId)
        childCoordinators.append(paymentCoord)
        
        paymentCoord.onFinish = { [weak self, weak paymentCoord] in
            self?.childCoordinators.removeAll { $0 === paymentCoord }
            paymentNav.dismiss(animated: true)
        }
        
        paymentCoord.start()
        navigationController.present(paymentNav, animated: true)
    }
}

// 3. Toza ViewController (Navigatsiyani umuman bilmaydi!)
public final class OrdersListViewController: UIViewController {
    public var onOrderSelected: ((String) -> Void)?
    
    func userTappedRow(orderId: String) {
        // Faqat o'z vazifasini bajaradi va hodisani uzatadi
        onOrderSelected?(orderId)
    }
}
```

---

## 4. Deeplink Boshqaruvi: Nega Coordinator Eng Yaxshisi?

Tashqi veb-saytdan `app://orders/details?id=772` havolasi kelganda:
`AppCoordinator` havolani parslaydi va uni `MainTabCoordinator` -> `OrdersCoordinator.showOrderDetail("772")` ga uzatadi. Ekranda qanday o'tishlar bo'lishi 1 ta joyda nazorat qilinadi!

---

## 5. Interaktiv Savol-Javob (Self-Check Quiz)

<details>
<summary><b>1-Savol: Coordinator patternida Child Coordinatorlar nima uchun 'childCoordinators' massivida saqlanishi kerak?</b> (Yechimni ko'rish uchun bosing)</summary>

**Tahlil va Yechim:**
Xotiradan o'chib ketmasligi uchun (Memory Lifecycle). Agar siz yangi `PaymentCoordinator` ochsangiz va uni massivda saqlamasangiz, funksiya tugashi bilanoq u xotiradan (ARC) o'chib ketadi va uning ichidagi delegat yoki closurelar ishlamay qoladi. Shuning uchun ota koordinator bolani massivda ushlab turadi, oqim tugagach esa massivdan o'chirib yuboradi (`removeAll`).
</details>

<details>
<summary><b>2-Savol: SwiftUI da Coordinator patterni qanday ishlatiladi?</b> (Yechimni ko'rish uchun bosing)</summary>

**Tahlil va Yechim:**
iOS 16+ da `NavigationPath` va `@Observable AppRouter` yaratiladi. Barcha View'lar routerga buyruq beradi (`router.push(.orderDetail(id))`), asosiy `NavigationStack(path: $router.path)` esa marshrutlar bo'yicha kerakli SwiftUI View'ni render qilib beradi.
</details>

---

## 6. Amaliy Topshiriq (Senior Challenge)

`AuthCoordinator` sinfini yarating:
* Oqim: `LoginViewController` -> agar hisob bo'lmasa -> `RegisterViewController` -> `OTPVerifyViewController`.
* Muvaffaqiyatli ro'yxatdan o'tgach, `AuthCoordinator` o'zining `onFinish` closure'ini chaqirsin va `AppCoordinator` asosiy ekranga o'tsin!
