# SnapKit 1: Kirish va O'rnatish — Nega SnapKit? NSLayoutConstraint azoblari va ilk layout

> **Holat:** Ushbu dars 2026-yil oktabr oyi holatiga ko'ra SnapKit 5.7+ versiyasiga asoslanib tayyorlangan. Zamonaviy iOS loyihalarda Auto Layout uchun eng ko'p ishlatiladigan vositadir.

## Mundarija
1. [NSLayoutConstraint azoblari](#nslayoutconstraint-azoblari)
2. [SnapKit nima va tarixi](#snapkit-nima)
3. [O'rnatish usullari](#ornatish)
4. [translatesAutoresizingMaskIntoConstraints siri](#translatesautoresizingmask)
5. [Birinchi SnapKit loyiha: "Hello SnapKit"](#birinchi-loyiha)
6. [snp.makeConstraints ichki mexanizmi](#make-constraints-mexanizmi)
7. [Boshlang'ich xatolar](#xatolar)
8. [Xulosa](#xulosa)
9. [Manbalar](#manbalar)

## 1. NSLayoutConstraint azoblari {#nslayoutconstraint-azoblari}

Apple'ning standart `NSLayoutConstraint` API'si Auto Layout'ni kod yordamida yozish uchun kuchli vosita bo'lsa-da, juda ko'p "qora mehnat" (boilerplate) talab qiladi.

Tasavvur qiling, ekranning markazida bitta qizil kvadrat (view) joylashtirmoqchimiz. Eni va bo'yi 100 pt bo'lsin.

Standart Apple API (NSLayoutConstraint) bilan:

```swift
import UIKit

class AppleLayoutViewController: UIViewController {
    let redView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        redView.backgroundColor = .red
        redView.translatesAutoresizingMaskIntoConstraints = false // Hech qachon unutmang!
        view.addSubview(redView)
        
        NSLayoutConstraint.activate([
            redView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            redView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            redView.widthAnchor.constraint(equalToConstant: 100),
            redView.heightAnchor.constraint(equalToConstant: 100)
        ])
    }
}
```

Endi xuddi shu layout'ni **SnapKit** yordamida qilamiz:

```swift
import UIKit
import SnapKit

class SnapKitLayoutViewController: UIViewController {
    let redView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        redView.backgroundColor = .red
        view.addSubview(redView) // Avval addSubview qiling
        
        redView.snp.makeConstraints { make in
            make.center.equalToSuperview() // CenterX va CenterY ni birlashtiradi
            make.size.equalTo(100)       // Width va Height ni 100 qiladi
        }
    }
}
```

**Kontrastga e'tibor bering!** SnapKit'da kod hajmi ikki barobar qisqardi, o'qilishi esa ingliz tili grammatikasi kabi tabiiy holatga keldi.

## 2. SnapKit nima va tarixi {#snapkit-nima}

**SnapKit** — bu Swift uchun Auto Layout DSL (Domain Specific Language). U Robert Payne va boshqa ochiq kodli dasturchilar tomonidan Objective-C dagi mashhur `Masonry` kutubxonasining vorisi sifatida yaratilgan.

- GitHub'da 20,000 dan ortiq yulduzchaga (stars) ega.
- iOS, macOS, va tvOS tizimlarini to'liq qo'llab-quvvatlaydi.
- Safe Area, Layout Guide kabi zamonaviy Apple texnologiyalari bilan mukammal integratsiya qilingan.

SnapKit'ning maqsadi bitta: **Auto Layout kodini qisqa, tushunarli va xavfsiz yozishni ta'minlash.**

## 3. O'rnatish usullari {#ornatish}

Loyihangizga SnapKit'ni qo'shishning bir necha yo'li mavjud.

### Swift Package Manager (SPM) — Tavsiya etilgan
Eng zamonaviy va oson usul:
1. Xcode menyusidan **File > Add Packages...** ni tanlang.
2. Qidiruv qatoriga URL manzilini kiriting: `https://github.com/SnapKit/SnapKit`
3. Dependency Rule sifatida **Up to Next Major Version** (5.7.x) ni tanlang.
4. **Add Package** tugmasini bosing.

### CocoaPods
Agar siz hali ham CocoaPods ishlatsangiz, `Podfile` fayliga quyidagini qo'shing:
```ruby
pod 'SnapKit', '~> 5.7'
```
So'ngra terminalda `pod install` buyrug'ini ishga tushiring.

### Tuist
Tuist kabi project generator'larida ishlayotgan bo'lsangiz, `Project.swift` faylida dependencies qismiga qo'shasiz:
```swift
.external(name: "SnapKit")
```

> **Senior eslatmasi:** Bugungi kunda (2026) SPM barcha zamonaviy iOS loyihalarida asosiy package menejeri hisoblanadi. Imkon qadar CocoaPods'dan SPM'ga o'tishni tavsiya qilamiz.

## 4. translatesAutoresizingMaskIntoConstraints siri {#translatesautoresizingmask}

Apple UIKit API'sida har doim kod orqali constraint berishdan oldin quyidagi qatorni yozish majburiy edi:
`view.translatesAutoresizingMaskIntoConstraints = false`

Bu xususiyat nima qiladi? Qadimgi iOS versiyalarida (Auto Layout yo'q paytda) view'lar `frame` va `autoresizing mask` orqali joylashardi. Apple Auto Layout'ni qo'shganda, eskirgan mask'larni avtomatik ravishda constraint'larga aylantirish imkonini qoldirdi. Ammo biz o'zimiz yangi constraint'lar yozayotganda, bu eski tizim (mask'lar) biz yozgan constraint'lar bilan ziddiyatga (conflict) kirishib ketadi.

Shuning uchun uni o'chirish kerak!

**SnapKit afzalligi:** `snp.makeConstraints` blokini chaqirganingizda, SnapKit buni **avtomatik** ravishda `false` ga o'zgartiradi! Siz bu qatorni boshqa hech qachon yozishingiz kerak emas.

## 5. Birinchi SnapKit loyiha: "Hello SnapKit" {#birinchi-loyiha}

Keling, endi 4 ta turli view'ni o'zaro bog'lagan holda bitta to'laqonli ekranni yig'amiz. 

**Talablar:**
- **Qizil view:** Tepadagi safe area'ga yopishgan, chap va o'ngdan 20pt masofa (padding), balandligi 100.
- **Yashil view:** Qizil view'ning pastida (16pt gap), chap tomonda, eni ekranning yarmi (50%), balandligi 50.
- **Ko'k view:** Ekranning mutlaq markazida, 200x200 o'lchamda.
- **Sariq view:** Ekranning eng pastida (safe area), chapdan o'nggacha cho'zilgan, balandligi 60.

```swift
import UIKit
import SnapKit

class HelloSnapKitViewController: UIViewController {

    // 1. View'larni yaratish
    let redView: UIView = {
        let v = UIView()
        v.backgroundColor = .systemRed
        return v
    }()
    
    let greenView: UIView = {
        let v = UIView()
        v.backgroundColor = .systemGreen
        return v
    }()
    
    let blueView: UIView = {
        let v = UIView()
        v.backgroundColor = .systemBlue
        return v
    }()
    
    let yellowView: UIView = {
        let v = UIView()
        v.backgroundColor = .systemYellow
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        setupSubviews()
        setupConstraints()
    }
    
    // 2. View hierarchyni o'rnatish
    private func setupSubviews() {
        view.addSubview(redView)
        view.addSubview(greenView)
        view.addSubview(blueView)
        view.addSubview(yellowView)
    }
    
    // 3. SnapKit yordamida Constraint'larni o'rnatish
    private func setupConstraints() {
        
        // Qizil view
        redView.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
            make.leading.trailing.equalToSuperview().inset(20) // ikki tomon ham 20pt
            make.height.equalTo(100)
        }
        
        // Yashil view
        greenView.snp.makeConstraints { make in
            make.top.equalTo(redView.snp.bottom).offset(16) // Qizil view ostida 16pt joy qoldirish
            make.leading.equalToSuperview().offset(20)
            make.width.equalToSuperview().multipliedBy(0.5) // Superview enining 50%
            make.height.equalTo(50)
        }
        
        // Ko'k view
        blueView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(CGSize(width: 200, height: 200)) // size orqali x/y o'lcham berish
        }
        
        // Sariq view
        yellowView.snp.makeConstraints { make in
            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(60)
        }
    }
}
```

```text
+------------------------------------+
|            [Safe Area]             |
|                                    |
|   +----------------------------+   |
|   |         Red View           |   |
|   +----------------------------+   |
|                                    |
|   +-------------+                  |
|   | Green View  |                  |
|   +-------------+                  |
|                                    |
|          +---------------+         |
|          |               |         |
|          |   Blue View   |         |
|          |               |         |
|          +---------------+         |
|                                    |
|   +----------------------------+   |
|   |        Yellow View         |   |
|   +----------------------------+   |
+------------------------------------+
```

## 6. snp.makeConstraints ichki mexanizmi {#make-constraints-mexanizmi}

Kod yozishda doim `snp.makeConstraints { make in }` formatini ishlatamiz. Xo'sh, bu o'zi qanday ishlaydi?

- `snp` — bu SnapKit tomonidan `UIView` ga qo'shilgan maxsus property bo'lib (extension orqali), SnapKit API'lariga kirish nuqtasi hisoblanadi.
- `makeConstraints` — closure qabul qiladigan funksiya.
- `make` — bu closure ichidagi `ConstraintMaker` obyekti. 

Siz `make.top` deganingizda, `ConstraintMakerExtendable` qaytadi. Siz `.equalTo(...)` qo'shganingizda esa u oxirigacha shakllanib, SnapKit xotirasiga saqlanadi. Closure tugagan zahoti, SnapKit barcha siz yozgan shartlarni to'playdi, Apple'ning `NSLayoutConstraint` obyektlariga o'giradi va bir vaqtning o'zida hammasini faollashtiradi (activate).

## 7. Eng ko'p uchraydigan boshlang'ich xatolar {#xatolar}

Boshlang'ich dasturchilar SnapKit o'rganayotganda asosan quyidagi xatoliklarga yo'l qo'yishadi:

1. **`addSubview` qilishdan oldin constraint yozish**
   ```swift
   // XATO: view.addSubview(redView) unutilgan
   redView.snp.makeConstraints { ... } 
   // Natija: Xotiradan Crash! ("... is not in any view hierarchy")
   ```

2. **Ota element (Superview) bo'lmaganda `equalToSuperview()` ni chaqirish**
   Bu ham yuqoridagi xatoga olib keladi. Qoidaga ko'ra: Layout boshlashdan oldin Hamma view'lar o'z `superview`'siga qo'shilgan bo'lishi shart.

3. **Bir-biriga qarama-qarshi constraintlar berish**
   ```swift
   make.width.equalTo(100)
   make.width.equalTo(200)
   ```
   Bunda loyiha crash bo'lmaydi, lekin Xcode console'da Auto Layout qichqira boshlaydi (Warning'lar).

> **Muhim:** To'g'ri odatni shakllantiring. Har bir view uchun oldin `addSubview`, keyin `makeConstraints`. Kodda `setupSubviews()` va `setupConstraints()` metodlarini alohida ajratib yozish bu borada katta yordam beradi.

## Xulosa {#xulosa}

Ushbu darsda biz SnapKit nega kerakligi, uning Apple standart API'lariga nisbatan afzalliklari, o'rnatish jarayoni va birinchi marta 4 xil view'ni joylashtirishni o'rgandik. Eng muhimi, Auto Layout endi uzundan-uzun kodlar yig'indisi emas, o'qilishi oson bo'lgan mantiqiy bloklardan iboratligini ko'rdik. 

Keyingi darsda `.offset()`, `.inset()`, `.multipliedBy()` va boshqa qiziqarli parametrlar bilan mukammal ishlashni o'rganamiz!

## Manbalar {#manbalar}

- [SnapKit rasmiy GitHub ombori](https://github.com/SnapKit/SnapKit)
- [Apple Auto Layout qo'llanmasi (Apple Docs)](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/)
- [SnapKit Rasmiy Dokumentatsiyasi](https://snapkit.github.io/SnapKit/docs/)
