# SwiftUI 7: SwiftUI ichki arxitekturasi — View identifikatsiyasi, Observation va UIKit bilan aloqa

> **Holat:** 2026-yil sentabr. SwiftUI oddiy deklarativ sintaksisdek ko'rinsa-da, uning kapoti ostida murakkab graf nazariyasi va identifikatsiya algoritmlari yotadi. Nega ba'zida `@State` o'z-o'zidan nolga tushib qoladi? Nega view keraksiz qayta chiziladi? Ushbu darsda Strukturaviy va Aniq identifikatsiya, Observation (@Observable) ning xotira darajasidagi ishlashi hamda UIKit bilan ikki tomonlama integratsiya ko'rib chiqiladi.

## Mundarija

1. [View identifikatsiyasi: Strukturaviy vs Aniq (Explicit)](#identity)
2. [Identifikatorning xotira hayot davriga ta'siri](#identity-lifetime)
3. [Observation Framework (@Observable) evolyutsiyasi](#observation)
4. [body qachon qayta ishga tushadi: _printChanges()](#body-evaluation)
5. [UIKit'ni SwiftUI'ga olib kirish: UIViewRepresentable](#uiview-representable)
6. [SwiftUI'ni UIKit'ga olib kirish: UIHostingController](#hosting-controller)
7. [Zamonaviy kataklar: UIHostingConfiguration](#hosting-configuration)
8. [Xulosa](#xulosa)
9. [Manbalar](#manbalar)

---

## 1. View identifikatsiyasi: Strukturaviy vs Aniq (Explicit) {#identity}

SwiftUI'da view struktura bo'lgani sababli, uning xotira manzili (pointer) doimiy emas. Tizim qaysi view o'zgarganini bilish uchun ikki xil identifikatsiyadan foydalanadi:

### 1. Strukturaviy identifikatsiya (Structural Identity)
View daraxtidagi ierarxik o'rni orqali aniqlanadi. Masalan:

```swift
import SwiftUI

struct ConditionalView: View {
  var isFlag: Bool

  var body: some View {
    if isFlag {
      CounterView() // Shox A (Identifikator: ConditionalView.True)
    } else {
      CounterView() // Shox B (Identifikator: ConditionalView.False)
    }
  }
}

struct CounterView: View {
  @State private var count = 0
  var body: some View {
    Button("Bosildi: \(count)") { count += 1 }
  }
}
```

> **Tuzoq:** Garchi ikkala shoxda ham `CounterView()` yozilgan bo'lsa-da, `isFlag` o'zgarganda SwiftUI eski shoxdagi view'ni butunlay o'chiradi va yangi shoxdagisini yaratadi — natijada `@State var count` **0 ga aylanib qoladi!**

### 2. Aniq identifikatsiya (Explicit Identity)
Dasturchi tomonidan `.id(...)` yoki `ForEach(items, id: \.id)` orqali beriladigan qat'iy identifikator.

---

## 2. Identifikatorning xotira hayot davriga ta'siri {#identity-lifetime}

Agar siz biror view'ning holatini majburan noldan tozalab, animatsiya bilan qayta ishga tushirmoqchi bo'lsangiz, uning `.id(...)` sini o'zgartirish kifoya:

```swift
import SwiftUI

struct ProfileResetContainer: View {
  @State private var sessionID = UUID()

  var body: some View {
    VStack {
      ProfileDetailsView()
        .id(sessionID) // sessionID o'zgarsa, ichki barcha State tozalanadi

      Button("Sessiyani yangilash") {
        sessionID = UUID()
      }
    }
  }
}

struct ProfileDetailsView: View {
  @State private var text = "Qoralama"
  var body: some View {
    TextField("Matn", text: $text)
  }
}
```

---

## 3. Observation Framework (@Observable) evolyutsiyasi {#observation}

iOS 17 dan boshlab (va iOS 26/27 da to'liq standart) Swift Syntax Makroslariga asoslangan **Observation Framework** kiritildi:

- **Eski usul (`ObservableObject` + `@Published`):** Ob'ekt ichidagi istalgan bitta `@Published` maydon o'zgarsa ham, butun view to'liq qayta hisoblanar edi.
- **Zamonaviy usul (`@Observable`):** Tizim maydon darajasida kuzatuv (**Property-level tracking**) olib boradi.

```swift
import SwiftUI

@Observable
public final class UserProfileModel {
  public var name: String = "Azimjon"
  public var age: Int = 26
  public var lastLogin: Date = Date()
}

public struct UserProfileView: View {
  @Bindable public var model: UserProfileModel

  public var body: some View {
    VStack(spacing: 8) {
      // Faqat name o'qilmoqda:
      Text(model.name)
      TextField("Ism", text: $model.name)
    }
  }
}
```

Agar fonda `model.age` yoki `model.lastLogin` qiymati o'zgarsa, `UserProfileView` **qayta chizilmaydi**, chunki uning `body`si faqat `name` ga bog'langan! Bu xotira va CPU sarfini keskin tejaydi.

---

## 4. body qachon qayta ishga tushadi: _printChanges() {#body-evaluation}

SwiftUI'da `body` quyidagi 4 holatda qayta hisoblanadi:
1. View'ning o'z `@State` o'zgaruvchisi o'zgarganda;
2. `body` ichida o'qilgan `@Observable` modeli maydoni o'zgarganda;
3. `@Environment` qiymati (masalan, rang mavzusi) yangilanganda;
4. Ota ko'rinishdan uzatilgan tashqi parametr o'zgarganda.

### Nosozliklarni qidirish (Debugging):
Qaysi sababga ko'ra ko'rinish qayta chizilayotganini bilish uchun maxsus yashirin metoddan foydalaniladi:

```swift
import SwiftUI

struct DebuggingView: View {
  @State private var count = 0

  var body: some View {
    #if DEBUG
    let _ = Self._printChanges()
    #endif

    Button("Soni: \(count)") {
      count += 1
    }
  }
}
```

Xcode konsolida: `DebuggingView: @self, _count changed.` degan aniq diagnostika chiqadi.

---

## 5. UIKit'ni SwiftUI'ga olib kirish: UIViewRepresentable {#uiview-representable}

SwiftUI'da hali mavjud bo'lmagan yoki murakkab UIKit komponentlarini (masalan, maxsus datchiklar, WebView yoki kamera ko'rinishi) SwiftUI'ga o'rash:

```swift
import SwiftUI
import UIKit

public struct NativeSpinner: UIViewRepresentable {
  public var isSpinning: Bool

  public func makeUIView(context: Context) -> UIActivityIndicatorView {
    UIActivityIndicatorView(style: .medium)
  }

  public func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
    if isSpinning {
      uiView.startAnimating()
    } else {
      uiView.stopAnimating()
    }
  }
}
```

---

## 6. SwiftUI'ni UIKit'ga olib kirish: UIHostingController {#hosting-controller}

Mavjud UIKit arxitekturasidagi ekran ichiga yangi SwiftUI modulini joylashtirish:

```swift
import SwiftUI
import UIKit

@MainActor
func embedSwiftUIView(in parentVC: UIViewController) {
  let swiftUIView = Text("Salom SwiftUI!")
  let hostingController = UIHostingController(rootView: swiftUIView)

  parentVC.addChild(hostingController)
  hostingController.view.frame = CGRect(x: 20, y: 100, width: 300, height: 100)
  parentVC.view.addSubview(hostingController.view)
  hostingController.didMove(toParent: parentVC)
}
```

---

## 7. Zamonaviy kataklar: UIHostingConfiguration {#hosting-configuration}

iOS 16+ dan boshlab `UITableViewCell` yoki `UICollectionViewCell` ichida maxsus subview yaratish shart emas — to'g'ridan-to'g'ri **`UIHostingConfiguration`** orqali SwiftUI ko'rinishini katakka o'rnatish mumkin:

```swift
import SwiftUI
import UIKit

@MainActor
func configureCustomCell(cell: UITableViewCell, title: String) {
  cell.contentConfiguration = UIHostingConfiguration {
    HStack {
      Image(systemName: "checkmark.seal.fill")
        .foregroundStyle(.blue)
      Text(title)
        .font(.body)
      Spacer()
    }
    .padding(.horizontal, 16)
  }
}
```

---

## 8. Xulosa {#xulosa}

- Strukturaviy identifikatsiya view daraxtidagi shoxlarga bog'liq; shartli bloklarda (`if-else`) holat yo'qolib ketmasligi uchun ehtiyot bo'lish lozim.
- `.id(...)` identifikatori o'zgarganda SwiftUI ob'ektni xotiradan to'liq tozalab, qayta tiklaydi.
- `@Observable` makrosi faqat `body` ichida real o'qilgan maydonlarni kuzatadi va unumdorlikni keskin oshiradi.
- `Self._printChanges()` orqali keraksiz qayta chizilish sabablarini tezkor aniqlash mumkin.
- `UIHostingConfiguration` UIKit ro'yxatlarida SwiftUI afzalliklaridan foydalanishning eng zamonaviy usulidir.

---

## Manbalar {#manbalar}

1. [Demystify SwiftUI — WWDC21](https://developer.apple.com/videos/play/wwdc2021/10022/)
2. [Discover Observation in SwiftUI — WWDC23](https://developer.apple.com/videos/play/wwdc2023/10149/)
3. [UIViewRepresentable — Apple Documentation](https://developer.apple.com/documentation/swiftui/uiviewrepresentable)
4. [UIHostingConfiguration — Apple Documentation](https://developer.apple.com/documentation/uikit/uihostingconfiguration)
