Azimjon Abdurasulov

SnapKit 15: Amaliyot — 30 ta Vizual UI Topshiriq (Zero to Hero Challenge)

🧩 SnapKit — Zero to Hero

SnapKit 15: Amaliyot — 30 ta Vizual UI Topshiriq (Zero to Hero Challenge)

Holat: Ushbu qo'llanma 2026-yil oktabr holatiga ko'ra SnapKit 5.7+ va Swift 6 talablari asosida tayyorlangan. Barcha kodlar zamonaviy @MainActor, UIKit Auto Layout va SwiftUI ekvivalentlari bilan boyitilgan.

Auto Layout va SnapKit bo'yicha nazariy bilimlarni o'rganish — bu yo'lning atigi 30% qismi. Haqiqiy mahorat faqat va faqat amaliyot orqali shakllanadi. Professional iOS dasturchisi dizayner chizgan har qanday UI sxemani ko'rishi bilanoq miyasida constraint'lar zanjirini qurishi, qaysi element qaysi biriga bog'lanishini, qaysi biri qisqarib qaysi biri cho'zilishini darhol his qila olishi zarur.

Ushbu amaliy darsda siz uchun 30 ta maxsus vizual topshiriq tayyorlandi. Ular oddiy poydevordan boshlanib, real App Store ilovalaridagi eng murakkab interfeyslargacha (ProfileView, HomeView, Chat, Fintech, Food Delivery, Crypto, App Store Today, Fitness, Checkout, Full Podcast Player) bosqichma-bosqich qiyinlashib boradi.


🧭 Mashg'ulot Qoidalari va Tavsiyalar

  1. Avval mustaqil bajaring: Har bir topshiriqdagi grafik sxemani (rasmni) va texnik talablarni diqqat bilan o'rganing. Yechimni ochishdan oldin yangi Xcode Playground yoki loyihada kod yozib ko'ring.
  2. Kodni tekshiring: Agar yechimni topishda qiyinchilikka duch kelsangiz yoki o'z kodingizni eng toza arxitektura bilan solishtirmoqchi bo'lsangiz, "💡 Kodni ko'rish" tugmasini bosing.
  3. Uchala texnologiyani taqqoslang: Har bir vazifada sizga 3 xil yechim taqdim etiladi:
  4. SnapKit (Asosiy maqsadimiz): Minimal, o'qilishi oson va qulay DSL.
  5. Klassik UIKit (NSLayoutConstraint): Nativ Anchor tizimi (SnapKit qanchalik mehnatni tejashini ko'rish uchun).
  6. SwiftUI ekvivalenti: Zamonaviy deklarativ yondashuv (dunyoqarashni kengaytirish uchun).
  7. Pro Tip va arxitektura xulosalariga e'tibor bering: Har bir yechim ostidagi professional maslahatlar sizni intervyularda yoki katta loyihalarda uchraydigan constraint buzilishlaridan asraydi.

📊 Qiyinchilik Darajalari

DarajaVazifalarQamrab Olingan Mavzular
🟢 Oson (Easy)01 – 05Center, Edges Inset, Vertical Spacing, Safe Area, Avatar & Label
🟡 O'rta (Medium)06 – 11Aspect Ratio (16:9), Overlapping Badge, Dynamic Width (Chat Bubble), 3 Equal Columns, Hugging/Compression Priority, Notification Banner
🟠 Qiyin (Hard)12 – 16E-Commerce Product Card, Floating Action Button (FAB), Dynamic Self-Sizing Cell, UIScrollView va ContentView, Segmented Moving Indicator
🔴 Qahramon (Hero)17 – 20Apple Music/Spotify Mini-Player, Instagram Stories Concentric Rings, Bank Card (1.586 ratio), Modern Paywall Subscription Card
👑 Titan (Real-World Screens)21 – 30Instagram Profile, E-Commerce Home Feed, Telegram Chat Room, Fintech Banking, Food Delivery Detail, Crypto Order Book, App Store Today, Fitness Dashboard, Checkout Summary, Full Podcast Player

🟢 Topshiriq 01: Markazdagi Kvadrat (Center Square)

Daraja: Oson (Easy) | Maqsad: Ekran markazida o'zgarmas 120x120 o'lchamli kvadrat shaklidagi view'ni joylashtirish.

Ushbu topshiriq SnapKit'dagi eng asosiy poydevor tushunchalar: center (markazlashtirish) va size (aniq o'lcham belgilash) bilan ishlashni mustahkamlaydi.

Vizual Sxema (UI Mockup)

Topshiriq 01: Markazdagi Kvadrat (Center Square)

📋 Texnik Talablar va Cheklovlar

  • Kvadrat kengligi (width) va balandligi (height) aynan 120 pt bo'lishi kerak.
  • Kvadrat ota-ona (superview) ekranning gorizontal va vertikal markazida bo'lishi shart.
  • Burchaklar radiusi (cornerRadius): 16 pt.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task01View: UIView {
    private let blueBox: UIView = {
        let view = UIView()
        view.backgroundColor = .systemBlue
        view.layer.cornerRadius = 16
        view.clipsToBounds = true
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(blueBox)

        blueBox.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(120) // make.width.height.equalTo(120) bilan bir xil
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task01UIKitView: UIView {
    private let blueBox: UIView = {
        let view = UIView()
        view.backgroundColor = .systemBlue
        view.layer.cornerRadius = 16
        view.clipsToBounds = true
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(blueBox)

        NSLayoutConstraint.activate([
            blueBox.centerXAnchor.constraint(equalTo: centerXAnchor),
            blueBox.centerYAnchor.constraint(equalTo: centerYAnchor),
            blueBox.widthAnchor.constraint(equalToConstant: 120),
            blueBox.heightAnchor.constraint(equalToConstant: 120)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task01SwiftUIView: View {
    var body: some View {
        ZStack {
            Color(white: 0.1).ignoresSafeArea()
            
            RoundedRectangle(cornerRadius: 16)
                .fill(Color.blue)
                .frame(width: 120, height: 120)
        }
    }
}

💡 Pro Tip & Arxitektura siri: SnapKit'da make.size.equalTo(120) deb yozish make.width.equalTo(120) va make.height.equalTo(120) o'rnini bosadi. Agar eni va bo'yi har xil bo'lsa, make.size.equalTo(CGSize(width: 120, height: 80)) formatida berish mumkin.

</details>


🟢 Topshiriq 02: Chetlaridan Bir Xil Masofadagi Card (Edges Inset)

Daraja: Oson (Easy) | Maqsad: Ekranning to'rtta chetidan ham 20 pt masofa (padding) tashlab, to'liq cho'ziluvchi kartani hosil qilish.

To'rtta chetni (top, bottom, leading, trailing) alohida yozish o'rniga SnapKit'ning kuchli edges va inset sintaksisidan foydalanish ko'nikmasi.

Vizual Sxema (UI Mockup)

Topshiriq 02: Chetlaridan Bir Xil Masofadagi Card (Edges Inset)

📋 Texnik Talablar va Cheklovlar

  • Karta ota-onaning barcha 4 tomoniga (top, bottom, leading, trailing) bog'lanishi kerak.
  • Har bir chetdan aynan 20 pt ichkariga (inset) siljishi lozim.
  • Burchaklar radiusi: 14 pt, fon rangi: binafsha (systemPurple).

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task02View: UIView {
    private let contentCard: UIView = {
        let view = UIView()
        view.backgroundColor = .systemPurple
        view.layer.cornerRadius = 14
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(contentCard)

        contentCard.snp.makeConstraints { make in
            // Barcha 4 tomonni bir qatorda 20 pt ichkariga siljitish:
            make.edges.equalToSuperview().inset(20)
            
            // Yoki alohida insets:
            // make.edges.equalToSuperview().inset(UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20))
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task02UIKitView: UIView {
    private let contentCard: UIView = {
        let view = UIView()
        view.backgroundColor = .systemPurple
        view.layer.cornerRadius = 14
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(contentCard)

        NSLayoutConstraint.activate([
            contentCard.topAnchor.constraint(equalTo: topAnchor, constant: 20),
            contentCard.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
            contentCard.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
            contentCard.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task02SwiftUIView: View {
    var body: some View {
        ZStack {
            Color(white: 0.1).ignoresSafeArea()
            
            RoundedRectangle(cornerRadius: 14)
                .fill(Color.purple)
                .padding(20)
        }
    }
}

💡 Pro Tip & Arxitektura siri: Farqiga e'tibor bering: inset(20) deb yozganda SnapKit trailing va bottom uchun avtomatik ravishda manfiy ishora (-20) qo'llaydi. Agar siz offset(20) ishlatganingizda edi, pastki va o'ng chegaralar ekrandan tashqariga chiqib ketardi!

</details>


🟢 Topshiriq 03: Ketma-ket Ikkita Vertikal Karta (Spacing)

Daraja: Oson (Easy) | Maqsad: Biri ikkinchisining ostida joylashgan, orasi 16 pt bo'lgan ikkita kartani bog'lash.

Elementlar orasidagi munosabat: ikkinchi elementning yuqori qismini (top) birinchi elementning pastki qismiga (bottom) bog'lash amaliyoti.

Vizual Sxema (UI Mockup)

Topshiriq 03: Ketma-ket Ikkita Vertikal Karta (Spacing)

📋 Texnik Talablar va Cheklovlar

  • Ikkala karta kengligi ota-onaning yonlaridan 24 pt masofada bo'lsin.
  • Har bir kartaning balandligi aynan 85 pt.
  • Birinchi karta ota-onaning tepasidan 35 pt masofada.
  • Ikkinchi karta birinchi kartaning tagidan 16 pt oraliq bilan joylashsin.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task03View: UIView {
    private let topCard: UIView = {
        let v = UIView()
        v.backgroundColor = .systemBlue
        v.layer.cornerRadius = 12
        return v
    }()

    private let bottomCard: UIView = {
        let v = UIView()
        v.backgroundColor = .systemPurple
        v.layer.cornerRadius = 12
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(topCard)
        addSubview(bottomCard)

        topCard.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(35)
            make.leading.trailing.equalToSuperview().inset(24)
            make.height.equalTo(85)
        }

        bottomCard.snp.makeConstraints { make in
            make.top.equalTo(topCard.snp.bottom).offset(16)
            make.leading.trailing.equalTo(topCard) // topCard bilan bir xil kenglik
            make.height.equalTo(85)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task03UIKitView: UIView {
    private let topCard: UIView = {
        let v = UIView()
        v.backgroundColor = .systemBlue
        v.layer.cornerRadius = 12
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    private let bottomCard: UIView = {
        let v = UIView()
        v.backgroundColor = .systemPurple
        v.layer.cornerRadius = 12
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(topCard)
        addSubview(bottomCard)

        NSLayoutConstraint.activate([
            topCard.topAnchor.constraint(equalTo: topAnchor, constant: 35),
            topCard.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 24),
            topCard.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -24),
            topCard.heightAnchor.constraint(equalToConstant: 85),

            bottomCard.topAnchor.constraint(equalTo: topCard.bottomAnchor, constant: 16),
            bottomCard.leadingAnchor.constraint(equalTo: topCard.leadingAnchor),
            bottomCard.trailingAnchor.constraint(equalTo: topCard.trailingAnchor),
            bottomCard.heightAnchor.constraint(equalToConstant: 85)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task03SwiftUIView: View {
    var body: some View {
        VStack(spacing: 16) {
            RoundedRectangle(cornerRadius: 12)
                .fill(Color.blue)
                .frame(height: 85)

            RoundedRectangle(cornerRadius: 12)
                .fill(Color.purple)
                .frame(height: 85)
            
            Spacer()
        }
        .padding(.horizontal, 24)
        .padding(.top, 35)
        .background(Color(white: 0.1).ignoresSafeArea())
    }
}

💡 Pro Tip & Arxitektura siri: SnapKit'da make.leading.trailing.equalTo(topCard) deb yozish bir yo'la ikkita chetni bir xil qilib bog'laydi. Bu kodni ixchamlashtiradi va kelajakda topCard ning marginlari o'zgarsa, bottomCard ham avtomatik ergashadi.

</details>


🟢 Topshiriq 04: Bosh Banner va Pastki Qadalgan Tugma (Safe Area)

Daraja: Oson (Easy) | Maqsad: Yuqoridagi bannerni Safe Area tepasiga, pastki tugmani esa Safe Area pastki chegarasiga mustahkamlash.

iPhone'dagi Dynamic Island, Notch va pastki Home Bar tugmalari bilan to'qnash kelmaslik uchun safeAreaLayoutGuide bilan to'g'ri ishlash.

Vizual Sxema (UI Mockup)

Topshiriq 04: Bosh Banner va Pastki Qadalgan Tugma (Safe Area)

📋 Texnik Talablar va Cheklovlar

  • Header banner Safe Area tepasidan 8 pt pastda, balandligi 56 pt.
  • Bottom action button Safe Area ostidan 8 pt tepada, balandligi 48 pt, burchaklari 24 pt (pill shape).
  • Ikkala element ham yondan 16 pt masofada bo'lsin.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task04ViewController: UIViewController {
    private let headerBanner: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(white: 0.2, alpha: 1.0)
        v.layer.cornerRadius = 10
        return v
    }()

    private let continueButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("Davom etish", for: .normal)
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel?.font = .systemFont(ofSize: 15, weight: .bold)
        btn.backgroundColor = .systemBlue
        btn.layer.cornerRadius = 24
        return btn
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        view.addSubview(headerBanner)
        view.addSubview(continueButton)

        headerBanner.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(8)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(56)
        }

        continueButton.snp.makeConstraints { make in
            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom).offset(-8)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(48)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task04UIKitViewController: UIViewController {
    private let headerBanner: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(white: 0.2, alpha: 1.0)
        v.layer.cornerRadius = 10
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    private let continueButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("Davom etish", for: .normal)
        btn.setTitleColor(.white, for: .normal)
        btn.backgroundColor = .systemBlue
        btn.layer.cornerRadius = 24
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        view.addSubview(headerBanner)
        view.addSubview(continueButton)

        let safe = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            headerBanner.topAnchor.constraint(equalTo: safe.topAnchor, constant: 8),
            headerBanner.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            headerBanner.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            headerBanner.heightAnchor.constraint(equalToConstant: 56),

            continueButton.bottomAnchor.constraint(equalTo: safe.bottomAnchor, constant: -8),
            continueButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            continueButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            continueButton.heightAnchor.constraint(equalToConstant: 48)
        ])
    }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task04SwiftUIView: View {
    var body: some View {
        VStack {
            RoundedRectangle(cornerRadius: 10)
                .fill(Color(white: 0.2))
                .frame(height: 56)
                .padding(.top, 8)
                .padding(.horizontal, 16)

            Spacer()

            Button(action: {}) {
                Text("Davom etish")
                    .font(.headline)
                    .foregroundColor(.white)
                    .frame(maxWidth: .infinity)
                    .frame(height: 48)
                    .background(Color.blue)
                    .clipShape(Capsule())
            }
            .padding(.bottom, 8)
            .padding(.horizontal, 16)
        }
        .background(Color(white: 0.08).ignoresSafeArea())
    }
}

💡 Pro Tip & Arxitektura siri: SnapKit'da view.safeAreaLayoutGuide.snp.top orqali to'g'ridan-to'g'ri bog'lanish eng xavfsiz yo'ldir. Hech qachon ekranning mutlaq top chegarasiga fiksatsiyalangan raqam bermang, chunki iPhone SE (notch yo'q), iPhone 13 (notch bor) va iPhone 15/16 (Dynamic Island) har xil balandlikka ega!

</details>


🟢 Topshiriq 05: Doiraviy Profil Rasmi va Yonidagi Matn

Daraja: Oson (Easy) | Maqsad: Chap tomonda 64x64 doiraviy avatar, uning o'ng tomonida esa vertikal markazlashgan Title va Subtitle yozuvlarini hosil qilish.

Gorizontal zanjir (Avatar -> Text) va matnlar guruhini umumiy konteyner yoki avatarga nisbatan vertikal markazlashtirish usuli.

Vizual Sxema (UI Mockup)

Topshiriq 05: Doiraviy Profil Rasmi va Yonidagi Matn

📋 Texnik Talablar va Cheklovlar

  • Avatar: 64x64 pt, burchak radiusi 32 pt (to'liq doira), chapdan 16 pt.
  • Matnlar avatardan 12 pt o'ngda boshlansin.
  • Title: qalin 15 pt matn. Subtitle: och 12 pt matn, title'dan 4 pt pastda.
  • Title va Subtitle juftligi avatarga nisbatan vertikal markazlashgan bo'lsin.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task05View: UIView {
    private let avatarImageView: UIImageView = {
        let iv = UIImageView()
        iv.backgroundColor = .systemBlue
        iv.layer.cornerRadius = 32
        iv.clipsToBounds = true
        return iv
    }()

    private let titleLabel: UILabel = {
        let l = UILabel()
        l.text = "Azimjon Pulatov"
        l.textColor = .white
        l.font = .systemFont(ofSize: 15, weight: .bold)
        return l
    }()

    private let subtitleLabel: UILabel = {
        let l = UILabel()
        l.text = "iOS Software Engineer"
        l.textColor = .systemGray
        l.font = .systemFont(ofSize: 12, weight: .regular)
        return l
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(avatarImageView)
        addSubview(titleLabel)
        addSubview(subtitleLabel)

        avatarImageView.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
            make.size.equalTo(64)
        }

        titleLabel.snp.makeConstraints { make in
            make.leading.equalTo(avatarImageView.snp.trailing).offset(12)
            make.trailing.lessThanOrEqualToSuperview().offset(-16)
            make.bottom.equalTo(avatarImageView.snp.centerY).offset(-2)
        }

        subtitleLabel.snp.makeConstraints { make in
            make.leading.equalTo(titleLabel)
            make.trailing.lessThanOrEqualToSuperview().offset(-16)
            make.top.equalTo(avatarImageView.snp.centerY).offset(2)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task05UIKitView: UIView {
    private let avatarImageView: UIImageView = {
        let iv = UIImageView()
        iv.backgroundColor = .systemBlue
        iv.layer.cornerRadius = 32
        iv.clipsToBounds = true
        iv.translatesAutoresizingMaskIntoConstraints = false
        return iv
    }()

    private let titleLabel: UILabel = {
        let l = UILabel()
        l.text = "Azimjon Pulatov"
        l.textColor = .white
        l.font = .systemFont(ofSize: 15, weight: .bold)
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    private let subtitleLabel: UILabel = {
        let l = UILabel()
        l.text = "iOS Software Engineer"
        l.textColor = .systemGray
        l.font = .systemFont(ofSize: 12, weight: .regular)
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(avatarImageView)
        addSubview(titleLabel)
        addSubview(subtitleLabel)

        NSLayoutConstraint.activate([
            avatarImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
            avatarImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            avatarImageView.widthAnchor.constraint(equalToConstant: 64),
            avatarImageView.heightAnchor.constraint(equalToConstant: 64),

            titleLabel.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: 12),
            titleLabel.bottomAnchor.constraint(equalTo: avatarImageView.centerYAnchor, constant: -2),

            subtitleLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor),
            subtitleLabel.topAnchor.constraint(equalTo: avatarImageView.centerYAnchor, constant: 2)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task05SwiftUIView: View {
    var body: some View {
        HStack(spacing: 12) {
            Circle()
                .fill(Color.blue)
                .frame(width: 64, height: 64)

            VStack(alignment: .leading, spacing: 4) {
                Text("Azimjon Pulatov")
                    .font(.system(size: 15, weight: .bold))
                    .foregroundColor(.white)

                Text("iOS Software Engineer")
                    .font(.system(size: 12))
                    .foregroundColor(.gray)
            }

            Spacer()
        }
        .padding(.horizontal, 16)
        .frame(height: 96)
        .background(Color(white: 0.1).ignoresSafeArea())
    }
}

💡 Pro Tip & Arxitektura siri: Ikkita satrli matnni vertikal markazlashtirishning ajoyib usuli: titleLabel.bottom ni markaz chizig'iga (centerY.offset(-2)), subtitleLabel.top ni esa markaz chizig'iga (centerY.offset(2)) bog'lashdir. Bu hech qanday qo'shimcha container view talab qilmaydi!

</details>


🟡 Topshiriq 06: 16:9 Nisbatdagi Video Player Karta

Daraja: O'rta (Medium) | Maqsad: Ekran kengligiga moslashuvchan, balandligi esa har doim 16:9 nisbatda avtomatik saqlanib turuvchi video player container yaratish.

SnapKit'dagi multipliedBy yordamida ekranning har qanday kengligida (iPhone, iPad, Landscape) to'g'ri proporsiyani saqlash texnikasi.

Vizual Sxema (UI Mockup)

Topshiriq 06: 16:9 Nisbatdagi Video Player Karta

📋 Texnik Talablar va Cheklovlar

  • Video kartasi yonlardan 24 pt masofa bilan ota-onaga bog'lansin.
  • Balandlik (height) kenglikka (width) nisbatan qat'iy 9/16 (0.5625) ko'paytuvchisi bilan o'rnatilsin.
  • Karta markazida 48x48 o'lchamdagi play tugmasi doirasi bo'lsin.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task06View: UIView {
    private let videoPlayerCard: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(white: 0.15, alpha: 1.0)
        v.layer.cornerRadius = 12
        v.layer.borderWidth = 1.5
        v.layer.borderColor = UIColor.systemGreen.cgColor
        return v
    }()

    private let playButton: UIButton = {
        let btn = UIButton(type: .system)
        let config = UIImage.SymbolConfiguration(pointSize: 22, weight: .bold)
        btn.setImage(UIImage(systemName: "play.fill", withConfiguration: config), for: .normal)
        btn.tintColor = .white
        btn.backgroundColor = .systemGreen
        btn.layer.cornerRadius = 24
        return btn
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        addSubview(videoPlayerCard)
        videoPlayerCard.addSubview(playButton)

        videoPlayerCard.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.trailing.equalToSuperview().inset(24)
            // 16:9 Aspect Ratio: balandlik = kenglik * (9.0 / 16.0)
            make.height.equalTo(videoPlayerCard.snp.width).multipliedBy(9.0 / 16.0)
        }

        playButton.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(48)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task06UIKitView: UIView {
    private let videoPlayerCard: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(white: 0.15, alpha: 1.0)
        v.layer.cornerRadius = 12
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        addSubview(videoPlayerCard)

        NSLayoutConstraint.activate([
            videoPlayerCard.centerYAnchor.constraint(equalTo: centerYAnchor),
            videoPlayerCard.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 24),
            videoPlayerCard.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -24),
            // UIKit'da multiplier yordamida aspect ratio:
            videoPlayerCard.heightAnchor.constraint(
                equalTo: videoPlayerCard.widthAnchor,
                multiplier: 9.0 / 16.0
            )
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task06SwiftUIView: View {
    var body: some View {
        ZStack {
            Color(white: 0.08).ignoresSafeArea()

            ZStack {
                RoundedRectangle(cornerRadius: 12)
                    .fill(Color(white: 0.15))
                    .aspectRatio(16/9, contentMode: .fit)

                Circle()
                    .fill(Color.green)
                    .frame(width: 48, height: 48)
                    .overlay(
                        Image(systemName: "play.fill")
                            .foregroundColor(.white)
                    )
            }
            .padding(.horizontal, 24)
        }
    }
}

💡 Pro Tip & Arxitektura siri: Nisbat belgilashda Swift'dagi bo'lish amalini ehtiyotkorlik bilan yozing: 9 / 16 butun sonli bo'lish bo'lgani uchun natija 0 bo'lib qoladi! Doimo float formatda 9.0 / 16.0 yozishni unutmang.

</details>


🟡 Topshiriq 07: Profil Rasmi Burchagidagi Online Status Dot

Daraja: O'rta (Medium) | Maqsad: 80x80 profil rasmining pastki o'ng burchagida qisman chiqib turuvchi 24x24 online status nishonini (badge) joylashtirish.

Elementlarni bir-birining ustiga (overlap) qadash va burchak koordinatalarini nozik offset bilan surish amaliyoti.

Vizual Sxema (UI Mockup)

Topshiriq 07: Profil Rasmi Burchagidagi Online Status Dot

📋 Texnik Talablar va Cheklovlar

  • Avatar: 80x80 pt o'lcham, burchak radiusi 40 pt.
  • Status badge: 24x24 pt, yashil rang, oq yoki to'q chegara (border: 3 pt).
  • Status badge markazi avatarning pastki o'ng chetidan 2 pt tashqariga siljisin.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task07View: UIView {
    private let avatarImageView: UIImageView = {
        let iv = UIImageView()
        iv.backgroundColor = .systemPurple
        iv.layer.cornerRadius = 40
        iv.clipsToBounds = true
        return iv
    }()

    private let statusDot: UIView = {
        let v = UIView()
        v.backgroundColor = .systemGreen
        v.layer.cornerRadius = 12
        v.layer.borderWidth = 3
        v.layer.borderColor = UIColor(white: 0.1, alpha: 1.0).cgColor
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(avatarImageView)
        addSubview(statusDot) // statusDot avatardan ustun turishi uchun keyin qo'shiladi

        avatarImageView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(80)
        }

        statusDot.snp.makeConstraints { make in
            make.size.equalTo(24)
            // Avatarning pastki-o'ng burchagiga mahkamlash:
            make.bottom.equalTo(avatarImageView.snp.bottom).offset(2)
            make.trailing.equalTo(avatarImageView.snp.trailing).offset(2)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task07UIKitView: UIView {
    private let avatarImageView: UIImageView = {
        let iv = UIImageView()
        iv.backgroundColor = .systemPurple
        iv.layer.cornerRadius = 40
        iv.clipsToBounds = true
        iv.translatesAutoresizingMaskIntoConstraints = false
        return iv
    }()

    private let statusDot: UIView = {
        let v = UIView()
        v.backgroundColor = .systemGreen
        v.layer.cornerRadius = 12
        v.layer.borderWidth = 3
        v.layer.borderColor = UIColor(white: 0.1, alpha: 1.0).cgColor
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(avatarImageView)
        addSubview(statusDot)

        NSLayoutConstraint.activate([
            avatarImageView.centerXAnchor.constraint(equalTo: centerXAnchor),
            avatarImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
            avatarImageView.widthAnchor.constraint(equalToConstant: 80),
            avatarImageView.heightAnchor.constraint(equalToConstant: 80),

            statusDot.widthAnchor.constraint(equalToConstant: 24),
            statusDot.heightAnchor.constraint(equalToConstant: 24),
            statusDot.bottomAnchor.constraint(equalTo: avatarImageView.bottomAnchor, constant: 2),
            statusDot.trailingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: 2)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task07SwiftUIView: View {
    var body: some View {
        ZStack {
            Color(white: 0.1).ignoresSafeArea()

            Circle()
                .fill(Color.purple)
                .frame(width: 80, height: 80)
                .overlay(
                    Circle()
                        .fill(Color.green)
                        .frame(width: 24, height: 24)
                        .overlay(Circle().stroke(Color(white: 0.1), lineWidth: 3))
                        .offset(x: 2, y: 2),
                    alignment: .bottomTrailing
                )
        }
    }
}

💡 Pro Tip & Arxitektura siri: Agar avatarImageView.clipsToBounds = true bo'lsa va siz statusDot ni uning ichiga (avatarImageView.addSubview(statusDot)) qo'shsangiz, chetdan chiqib turgan qismi qirqilib ketadi! Shu sababli doimo badge'larni tashqi umumiy view'ga qo'shib, keyin avatarga bog'lang.

</details>


🟡 Topshiriq 08: Moslashuvchan Xabar Pufakchasi (Chat Bubble)

Daraja: O'rta (Medium) | Maqsad: Telegram yoki iMessage kabi dinamik chat pufakchasini yaratish: qisqa matnda kichrayishi, lekin eng ko'p cho'zilganida ham ekran kengligining 75% idan oshmasligi kerak.

Tengsizliklar (greaterThanOrEqualTo va lessThanOrEqualTo) bilan ishlash mahorati.

Vizual Sxema (UI Mockup)

Topshiriq 08: Moslashuvchan Xabar Pufakchasi (Chat Bubble)

📋 Texnik Talablar va Cheklovlar

  • Pufakcha chap chetdan 16 pt masofada.
  • Minimal kenglik: 60 pt (greaterThanOrEqualTo).
  • Maksimal kenglik: ota-ona kengligining 75% qismi (lessThanOrEqualToSuperview().multipliedBy(0.75)).
  • Matn ko'p qatorli bo'lishi mumkin (numberOfLines = 0), pufakcha ichidagi padding 12 pt.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task08View: UIView {
    private let bubbleView: UIView = {
        let v = UIView()
        v.backgroundColor = .systemBlue
        v.layer.cornerRadius = 16
        return v
    }()

    private let messageLabel: UILabel = {
        let l = UILabel()
        l.text = "SnapKit yordamida Auto Layout yozish juda qulay va kod hajmini 3 baravar qisqartiradi!"
        l.textColor = .white
        l.font = .systemFont(ofSize: 15)
        l.numberOfLines = 0
        return l
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        addSubview(bubbleView)
        bubbleView.addSubview(messageLabel)

        bubbleView.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(60)
            make.leading.equalToSuperview().offset(16)
            // Cheklovlar:
            make.width.greaterThanOrEqualTo(60)
            make.width.lessThanOrEqualToSuperview().multipliedBy(0.75)
        }

        messageLabel.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(12)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task08UIKitView: UIView {
    private let bubbleView: UIView = {
        let v = UIView()
        v.backgroundColor = .systemBlue
        v.layer.cornerRadius = 16
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    private let messageLabel: UILabel = {
        let l = UILabel()
        l.text = "SnapKit yordamida Auto Layout yozish juda qulay va kod hajmini 3 baravar qisqartiradi!"
        l.textColor = .white
        l.font = .systemFont(ofSize: 15)
        l.numberOfLines = 0
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        addSubview(bubbleView)
        bubbleView.addSubview(messageLabel)

        let maxConstraint = bubbleView.widthAnchor.constraint(
            lessThanOrEqualTo: widthAnchor,
            multiplier: 0.75
        )

        NSLayoutConstraint.activate([
            bubbleView.topAnchor.constraint(equalTo: topAnchor, constant: 60),
            bubbleView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            bubbleView.widthAnchor.constraint(greaterThanOrEqualToConstant: 60),
            maxConstraint,

            messageLabel.topAnchor.constraint(equalTo: bubbleView.topAnchor, constant: 12),
            messageLabel.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: -12),
            messageLabel.leadingAnchor.constraint(equalTo: bubbleView.leadingAnchor, constant: 12),
            messageLabel.trailingAnchor.constraint(equalTo: bubbleView.trailingAnchor, constant: -12)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task08SwiftUIView: View {
    var body: some View {
        GeometryReader { proxy in
            VStack(alignment: .leading) {
                Text("SnapKit yordamida Auto Layout yozish juda qulay va kod hajmini 3 baravar qisqartiradi!")
                    .font(.system(size: 15))
                    .foregroundColor(.white)
                    .padding(12)
                    .background(Color.blue)
                    .clipShape(RoundedRectangle(cornerRadius: 16))
                    .frame(
                        minWidth: 60,
                        maxWidth: proxy.size.width * 0.75,
                        alignment: .leading
                    )
            }
            .padding(.horizontal, 16)
            .padding(.top, 60)
        }
        .background(Color(white: 0.08).ignoresSafeArea())
    }
}

💡 Pro Tip & Arxitektura siri: Matn bir necha qator bo'lishi uchun numberOfLines = 0 bo'lishi shart. UILabel o'zining tabiiy o'lchamini (intrinsicContentSize) hisoblab chiqaradi va faqatgina 75% limitga urilgandagina keyingi satrga o'tadi.

</details>


🟡 Topshiriq 09: Uchta Teng Ustun (Three Equal Columns)

Daraja: O'rta (Medium) | Maqsad: Gorizontal ravishda yonma-yon joylashgan, kengligi bir-biriga mutlaqo teng bo'lgan va orasi 16 pt dan bo'lgan 3 ta kartani hosil qilish.

Teng kengliklarni zanjir usulida bir-biriga tenglash (make.width.equalTo(card1)) va chekka chegaralarni to'g'ri yopish.

Vizual Sxema (UI Mockup)

Topshiriq 09: Uchta Teng Ustun (Three Equal Columns)

📋 Texnik Talablar va Cheklovlar

  • 3 ta karta ekranning chap va o'ng chegarasidan 16 pt oraliqda bo'lsin.
  • Kartalar orasidagi masofa aynan 16 pt.
  • Har bir kartaning kengligi bir xil bo'lishi va balandligi 120 pt bo'lishi shart.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task09View: UIView {
    private let card1 = UIView()
    private let card2 = UIView()
    private let card3 = UIView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        [card1, card2, card3].enumerated().forEach { index, card in
            card.backgroundColor = [UIColor.systemBlue, UIColor.systemPurple, UIColor.systemGreen][index]
            card.layer.cornerRadius = 12
            addSubview(card)
        }

        card1.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
            make.height.equalTo(120)
        }

        card2.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalTo(card1.snp.trailing).offset(16)
            make.width.equalTo(card1) // 1-karta bilan teng kenglik
            make.height.equalTo(120)
        }

        card3.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalTo(card2.snp.trailing).offset(16)
            make.trailing.equalToSuperview().offset(-16) // o'ng tomonga qadaladi
            make.width.equalTo(card1) // 1-karta bilan teng kenglik
            make.height.equalTo(120)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task09UIKitView: UIView {
    private let card1 = UIView()
    private let card2 = UIView()
    private let card3 = UIView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)

        [card1, card2, card3].enumerated().forEach { index, card in
            card.backgroundColor = [UIColor.systemBlue, UIColor.systemPurple, UIColor.systemGreen][index]
            card.layer.cornerRadius = 12
            card.translatesAutoresizingMaskIntoConstraints = false
            addSubview(card)
        }

        NSLayoutConstraint.activate([
            card1.centerYAnchor.constraint(equalTo: centerYAnchor),
            card1.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            card1.heightAnchor.constraint(equalToConstant: 120),

            card2.centerYAnchor.constraint(equalTo: centerYAnchor),
            card2.leadingAnchor.constraint(equalTo: card1.trailingAnchor, constant: 16),
            card2.widthAnchor.constraint(equalTo: card1.widthAnchor),
            card2.heightAnchor.constraint(equalToConstant: 120),

            card3.centerYAnchor.constraint(equalTo: centerYAnchor),
            card3.leadingAnchor.constraint(equalTo: card2.trailingAnchor, constant: 16),
            card3.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            card3.widthAnchor.constraint(equalTo: card1.widthAnchor),
            card3.heightAnchor.constraint(equalToConstant: 120)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task09SwiftUIView: View {
    var body: some View {
        HStack(spacing: 16) {
            RoundedRectangle(cornerRadius: 12)
                .fill(Color.blue)
                .frame(height: 120)

            RoundedRectangle(cornerRadius: 12)
                .fill(Color.purple)
                .frame(height: 120)

            RoundedRectangle(cornerRadius: 12)
                .fill(Color.green)
                .frame(height: 120)
        }
        .padding(.horizontal, 16)
        .background(Color(white: 0.08).ignoresSafeArea())
    }
}

💡 Pro Tip & Arxitektura siri: Matematik formulaga e'tibor bering: 3 ta karta va 4 ta masofa (chap, 2 ta o'rtadagi, o'ng) berildi va oxirgi karta trailing ga qadalgach, Auto Layout har bir kartaning kengligini har qanday qurilma o'lchamida mustaqil hisoblab beradi.

</details>


🟡 Topshiriq 10: Sarlavha va Sana: Content Compression Resistance Priority

Daraja: O'rta (Medium) | Maqsad: Bitta qatorda chapda sarlavha, o'ngda sana. Agar sarlavha matni haddan tashqari uzun bo'lib ketsa ham, sana hech qachon siqilib qisqarmasligi, aksincha sarlavha '...' (truncate) bo'lishi kerak.

Constraint Priority, Content Compression Resistance va Content Hugging tushunchalarini amalda hal qilish.

Vizual Sxema (UI Mockup)

Topshiriq 10: Sarlavha va Sana: Content Compression Resistance Priority

📋 Texnik Talablar va Cheklovlar

  • titleLabel: chapda, uzayganda sig'may qolsa uch nuqta bo'lsin (.byTruncatingTail).
  • dateLabel: o'ngda, hech qachon qisqarmasin va matni to'liq ko'rinsin.
  • dateLabel'ning contentCompressionResistancePriority darajasi .required (1000) ga ko'tarilsin, titleLabel'niki esa .defaultLow (250) bo'lsin.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task10View: UIView {
    private let titleLabel: UILabel = {
        let l = UILabel()
        l.text = "Juda uzun topshiriq sarlavhasi: SnapKit va UIKit Auto Layout arxitekturasini o'rganish"
        l.textColor = .white
        l.font = .systemFont(ofSize: 15, weight: .semibold)
        l.lineBreakMode = .byTruncatingTail
        return l
    }()

    private let dateLabel: UILabel = {
        let l = UILabel()
        l.text = "Bugun, 18:30"
        l.textColor = .systemBlue
        l.font = .systemFont(ofSize: 13, weight: .bold)
        return l
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(titleLabel)
        addSubview(dateLabel)

        // Sanani siqilishdan qutqaruvchi kalit qator:
        dateLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
        titleLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

        titleLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
            make.trailing.lessThanOrEqualTo(dateLabel.snp.leading).offset(-12)
        }

        dateLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.trailing.equalToSuperview().offset(-16)
        }
    }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task10UIKitView: UIView {
    private let titleLabel: UILabel = {
        let l = UILabel()
        l.text = "Juda uzun topshiriq sarlavhasi: SnapKit va UIKit Auto Layout arxitekturasini o'rganish"
        l.textColor = .white
        l.font = .systemFont(ofSize: 15, weight: .semibold)
        l.lineBreakMode = .byTruncatingTail
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    private let dateLabel: UILabel = {
        let l = UILabel()
        l.text = "Bugun, 18:30"
        l.textColor = .systemBlue
        l.font = .systemFont(ofSize: 13, weight: .bold)
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.1, alpha: 1.0)
        addSubview(titleLabel)
        addSubview(dateLabel)

        dateLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
        titleLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

        NSLayoutConstraint.activate([
            titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
            titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: dateLabel.leadingAnchor, constant: -12),

            dateLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
            dateLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task10SwiftUIView: View {
    var body: some View {
        HStack(spacing: 12) {
            Text("Juda uzun topshiriq sarlavhasi: SnapKit va UIKit Auto Layout arxitekturasini o'rganish")
                .font(.system(size: 15, weight: .semibold))
                .foregroundColor(.white)
                .lineLimit(1)
                .truncationMode(.tail)

            Text("Bugun, 18:30")
                .font(.system(size: 13, weight: .bold))
                .foregroundColor(.blue)
                .fixedSize(horizontal: true, vertical: false) // Siqilishdan himoya
        }
        .padding(.horizontal, 16)
        .frame(height: 60)
        .background(Color(white: 0.1).ignoresSafeArea())
    }
}

💡 Pro Tip & Arxitektura siri: Intervyularda eng ko'p beriladigan savol: 'Ikki label yonma-yon turganda qaysi biri qisqarishini qanday boshqarasiz?' Javob: setContentCompressionResistancePriority orqali. Qaysi view'ning priority'si kichik bo'lsa (250), o'sha view birinchi bo'lib qisqaradi!

</details>


🟡 Topshiriq 11: Bildirishnoma Kartasi va Yopish Tugmasi

Daraja: O'rta (Medium) | Maqsad: Ekranning yuqorisida bildirishnoma banneri: chapda 36x36 icon, o'rtada 2 qatorli xabar matni, o'ngda esa 28x28 yopish tugmasi ('✕').

Uchta elementdan iborat gorizontal zanjir (Icon -> Flexible Text Stack -> Action Button) va ularni to'g'ri oraliqlar bilan joylashtirish.

Vizual Sxema (UI Mockup)

Topshiriq 11: Bildirishnoma Kartasi va Yopish Tugmasi

📋 Texnik Talablar va Cheklovlar

  • Banner: balandligi 80 pt, chetlaridan 16 pt oraliq, burchaklar radiusi 14 pt.
  • IconView: 36x36 pt, chapdan 16 pt, vertikal markazda.
  • CloseButton: 28x28 pt, o'ngdan 16 pt, vertikal markazda.
  • Matnlar maydoni Icon va CloseButton oralig'ini to'liq egallasin (orasi 12 pt dan).

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

final class Task11View: UIView {
    private let bannerCard: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(white: 0.15, alpha: 1.0)
        v.layer.cornerRadius = 14
        v.layer.borderWidth = 1
        v.layer.borderColor = UIColor.systemSky?.cgColor ?? UIColor.systemBlue.cgColor
        return v
    }()

    private let iconImageView: UIImageView = {
        let iv = UIImageView()
        iv.image = UIImage(systemName: "bell.badge.fill")
        iv.tintColor = .systemSky ?? .systemBlue
        iv.contentMode = .scaleAspectFit
        return iv
    }()

    private let titleLabel: UILabel = {
        let l = UILabel()
        l.text = "Yangi topshiriq tayyor"
        l.textColor = .white
        l.font = .systemFont(ofSize: 14, weight: .bold)
        return l
    }()

    private let bodyLabel: UILabel = {
        let l = UILabel()
        l.text = "SnapKit kursidan 20 ta amaliy vazifani boshlang."
        l.textColor = .systemGray
        l.font = .systemFont(ofSize: 11)
        l.numberOfLines = 2
        return l
    }()

    private let closeButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("✕", for: .normal)
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel?.font = .systemFont(ofSize: 13, weight: .bold)
        btn.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
        btn.layer.cornerRadius = 14
        return btn
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    private func setupUI() {
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        addSubview(bannerCard)
        bannerCard.addSubview(iconImageView)
        bannerCard.addSubview(titleLabel)
        bannerCard.addSubview(bodyLabel)
        bannerCard.addSubview(closeButton)

        bannerCard.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(60)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(80)
        }

        iconImageView.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
            make.size.equalTo(36)
        }

        closeButton.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.trailing.equalToSuperview().offset(-16)
            make.size.equalTo(28)
        }

        titleLabel.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(16)
            make.leading.equalTo(iconImageView.snp.trailing).offset(12)
            make.trailing.equalTo(closeButton.snp.leading).offset(-12)
        }

        bodyLabel.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(4)
            make.leading.trailing.equalTo(titleLabel)
        }
    }
}

private extension UIColor {
    static var systemSky: UIColor? { UIColor(red: 0.22, green: 0.74, blue: 0.97, alpha: 1.0) }
}
2. Klassik UIKit (NSLayoutConstraint) Taqqoslash
import UIKit

final class Task11UIKitView: UIView {
    private let bannerCard: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(white: 0.15, alpha: 1.0)
        v.layer.cornerRadius = 14
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    private let iconImageView: UIImageView = {
        let iv = UIImageView()
        iv.image = UIImage(systemName: "bell.badge.fill")
        iv.tintColor = .systemBlue
        iv.translatesAutoresizingMaskIntoConstraints = false
        return iv
    }()

    private let titleLabel: UILabel = {
        let l = UILabel()
        l.text = "Yangi topshiriq tayyor"
        l.textColor = .white
        l.font = .systemFont(ofSize: 14, weight: .bold)
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    private let closeButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("✕", for: .normal)
        btn.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
        btn.layer.cornerRadius = 14
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(white: 0.08, alpha: 1.0)
        addSubview(bannerCard)
        bannerCard.addSubview(iconImageView)
        bannerCard.addSubview(titleLabel)
        bannerCard.addSubview(closeButton)

        NSLayoutConstraint.activate([
            bannerCard.topAnchor.constraint(equalTo: topAnchor, constant: 60),
            bannerCard.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            bannerCard.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            bannerCard.heightAnchor.constraint(equalToConstant: 80),

            iconImageView.centerYAnchor.constraint(equalTo: bannerCard.centerYAnchor),
            iconImageView.leadingAnchor.constraint(equalTo: bannerCard.leadingAnchor, constant: 16),
            iconImageView.widthAnchor.constraint(equalToConstant: 36),
            iconImageView.heightAnchor.constraint(equalToConstant: 36),

            closeButton.centerYAnchor.constraint(equalTo: bannerCard.centerYAnchor),
            closeButton.trailingAnchor.constraint(equalTo: bannerCard.trailingAnchor, constant: -16),
            closeButton.widthAnchor.constraint(equalToConstant: 28),
            closeButton.heightAnchor.constraint(equalToConstant: 28),

            titleLabel.centerYAnchor.constraint(equalTo: bannerCard.centerYAnchor),
            titleLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 12),
            titleLabel.trailingAnchor.constraint(equalTo: closeButton.leadingAnchor, constant: -12)
        ])
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
3. SwiftUI Ekvivalenti
import SwiftUI

struct Task11SwiftUIView: View {
    var body: some View {
        HStack(spacing: 12) {
            Image(systemName: "bell.badge.fill")
                .font(.system(size: 20))
                .foregroundColor(.blue)
                .frame(width: 36, height: 36)

            VStack(alignment: .leading, spacing: 4) {
                Text("Yangi topshiriq tayyor")
                    .font(.system(size: 14, weight: .bold))
                    .foregroundColor(.white)

                Text("SnapKit kursidan 20 ta amaliy vazifani boshlang.")
                    .font(.system(size: 11))
                    .foregroundColor(.gray)
                    .lineLimit(2)
            }

            Spacer()

            Button(action: {}) {
                Text("✕")
                    .font(.system(size: 13, weight: .bold))
                    .foregroundColor(.white)
                    .frame(width: 28, height: 28)
                    .background(Color(white: 0.25))
                    .clipShape(Circle())
            }
        }
        .padding(16)
        .frame(height: 80)
        .background(Color(white: 0.15))
        .clipShape(RoundedRectangle(cornerRadius: 14))
        .padding(.horizontal, 16)
        .padding(.top, 60)
        .background(Color(white: 0.08).ignoresSafeArea())
    }
}

💡 Pro Tip & Arxitektura siri: Matn maydonining o'ng tomonini qat'iy ravishda closeButton.snp.leading ga bog'lang. Bu orqali xabar matni har qancha uzun bo'lsa ham yopish tugmasining ustiga chiqib ketmaydi.

</details>


🟠 Topshiriq 12: Do'kon Mahsulot Kartasi (Product Grid Card)

Daraja: Qiyin (Hard) | Maqsad: Zamonaviy e-commerce kartasi: rasm, uning burchagidagi chegarma nishoni, sarlavha, narx va pastki o'ngdagi dumaloq qo'shish tugmasi ('+').

Murakkab vizual ierarxiya, elementlararo bog'lanish va nisbatlarni toza boshqarish.

Vizual Sxema (UI Mockup)

Topshiriq 12: Do'kon Mahsulot Kartasi (Product Grid Card)

📋 Texnik Talablar va Cheklovlar

  • Karta: kengligi 220 pt, burchak radiusi 16 pt, fon to'q rangda.
  • Mahsulot rasmi: kartaning yuqori qismida, balandligi 110 pt, ichki margin 12 pt.
  • Chegarma nishoni (-25%): rasmining yuqori-chap burchagida 8 pt oraliqda.
  • Title va Category rasmdan pastda.
  • Pastda yashil narx ($249) va uning o'ng tomonida 36x36 o'lchamli dumaloq sariq '+' tugmasi.

<details> <summary>💡 Kodni ko'rish (SnapKit, UIKit va SwiftUI yechimlari)</summary>

1. SnapKit Yechimi (Asosiy)
import UIKit
import SnapKit

Markdown manba

iOS Lessons