Azimjon Abdurasulov

UIKit

Cheat Sheet'lar

UIKit Cheat Sheet

iOS dasturlashda UIKit frameworki orqali imperativ interfeyslar, View Lifecycle va Auto Layout bilan ishlash bo'yicha tezkor qo'llanma.


1. UIViewController Lifecycle (Hayotiy sikli)

MetodQachon chaqiriladi?Nima qilish kerak?
loadView()View xotiraga yuklanganda (faqat custom view o'rnatishda override qilinadi)self.view = CustomView()
viewDidLoad()View xotiraga bir marta yuklangandaUI elementlarni qo'shish, constraintlar, dastlabki API so'rov
viewWillAppear(_:)Ekran foydalanuvchiga ko'rinishidan oldin (har safar)UI yangilash, navigatsiya barini sozlash, klaviatura obunasi
viewWillLayoutSubviews()View'ning frame'lari o'lchanishidan oldinLayout o'zgarishlariga tayyorgarlik
viewDidLayoutSubviews()Auto Layout subview'lar o'lchamini hisoblab bo'lgandaGradient layer frame'larini yangilash, cornerRadius
viewDidAppear(_:)Ekran to'liq ko'ringandaAnimatsiyalarni boshlash, video ijro etish, analitika yuborish
viewWillDisappear(_:)Ekran yopilishidan oldinKlaviaturani tushirish, taymerlarni to'xtatish
viewDidDisappear(_:)Ekran butunlay yashiringandaOg'ir resurslarni pauza qilish
deinitController xotiradan tozalanayotgandaRetain cycle tekshirish, observerlarni tozalash

2. Programmatic UI & Auto Layout

Auto Layout kodda yozilganda har doim translatesAutoresizingMaskIntoConstraints = false bo'lishi shart!

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

    private let titleLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = .systemFont(ofSize: 18, weight: .bold)
        label.textColor = .label
        return label
    }()

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

    required init?(coder: NSCoder) { fatalError("init(coder:) unhandled") }

    private func setupLayout() {
        addSubview(avatarImageView)
        addSubview(titleLabel)

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

            // Title
            titleLabel.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: 12),
            titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            titleLabel.centerYAnchor.constraint(equalTo: avatarImageView.centerYAnchor)
        ])
    }
}

Content Hugging & Compression Resistance:

  • Hugging (Kengayishga qarshilik): Element o'z matnidan katta bo'lib ketmasin.
label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
  • Compression Resistance (Siqilishga qarshilik): Matn qisqarib (...) ketmasin.
label.setContentCompressionResistancePriority(.required, for: .horizontal)

3. UIStackView

Kodda elementlarni chiroyli joylashtirishning eng qulay usuli.

let stack = UIStackView(arrangedSubviews: [nameLabel, descLabel])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .vertical          // .horizontal yoki .vertical
stack.spacing = 8
stack.alignment = .fill         // .leading, .trailing, .center, .fill
stack.distribution = .fillProportionally // .fillEqually, .equalSpacing

4. Modern UICollectionView & DiffableDataSource

iOS 14+ da zamonaviy List/Grid yaratish usuli (Delegatesiz va crash'larsiz).

// 1. Model
struct Item: Hashable {
    let id = UUID()
    let title: String
}

enum Section { case main }

// 2. ViewController ichida
final class ItemsViewController: UIViewController {
    private var collectionView: UICollectionView!
    private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!

    override func viewDidLoad() {
        super.viewDidLoad()
        configureHierarchy()
        configureDataSource()
        applyInitialData()
    }

    private func configureHierarchy() {
        // iOS 14+ List Configuration
        var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        let layout = UICollectionViewCompositionalLayout.list(using: config)
        
        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
        collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(collectionView)
    }

    private func configureDataSource() {
        // Cell Registration
        let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Item> { cell, indexPath, item in
            var content = cell.defaultContentConfiguration()
            content.text = item.title
            content.image = UIImage(systemName: "star")
            cell.contentConfiguration = content
        }

        dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, item in
            collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
        }
    }

    private func applyInitialData() {
        var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
        snapshot.appendSections([.main])
        snapshot.appendItems([Item(title: "Swift"), Item(title: "UIKit"), Item(title: "SwiftUI")])
        dataSource.apply(snapshot, animatingDifferences: true)
    }
}

5. Delegation & Target-Action

Delegate Pattern:

protocol CustomButtonDelegate: AnyObject {
    func didTapActionButton(_ sender: CustomButton)
}

final class CustomButton: UIView {
    weak var delegate: CustomButtonDelegate? // weak shart!

    private func handleTap() {
        delegate?.didTapActionButton(self)
    }
}

Target-Action:

button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)

@objc private func buttonTapped() {
    print("Tugma bosildi")
}

6. Navigatsiya va Modallar (Navigation & Modals)

// 1. Push (NavigationController ichida)
let detailVC = DetailViewController()
navigationController?.pushViewController(detailVC, animated: true)

// Pop (Orqaga)
navigationController?.popViewController(animated: true)

// 2. Modal Present
let modalVC = SheetViewController()
modalVC.modalPresentationStyle = .pageSheet // yoki .fullScreen, .formSheet

if let sheet = modalVC.sheetPresentationController {
    sheet.detents = [.medium(), .large()]
    sheet.prefersGrabberVisible = true
}
present(modalVC, animated: true)

// Dismiss
dismiss(animated: true)

7. Alerts & ActionSheet

let alert = UIAlertController(title: "O'chirish", message: "Ishonchingiz komilmi?", preferredStyle: .alert)

let deleteAction = UIAlertAction(title: "Ha, o'chir", style: .destructive) { _ in
    // Delete logikasi
}
let cancelAction = UIAlertAction(title: "Bekor qilish", style: .cancel)

alert.addAction(deleteAction)
alert.addAction(cancelAction)
present(alert, animated: true)

8. UIView Animatsiyalari

// Oddiy animatsiya
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseInOut]) {
    self.cardView.alpha = 1.0
    self.cardView.transform = .identity
}

// Spring Animatsiya (Sakrash effekti)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5) {
    self.button.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
}

// Interaktiv Animator (UIViewPropertyAnimator)
let animator = UIViewPropertyAnimator(duration: 0.4, curve: .easeOut) {
    self.view.backgroundColor = .systemRed
}
animator.startAnimation()

9. Gestures (Harakatlar)

let tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped(_:)))
tap.numberOfTapsRequired = 1
containerView.addGestureRecognizer(tap)
containerView.isUserInteractionEnabled = true // Majburiy!

@objc private func viewTapped(_ gesture: UITapGestureRecognizer) {
    print("Bosildi:", gesture.location(in: view))
}

Markdown manba

iOS Lessons