UICollectionView — iOS uchun UIKit-ning kuchli komponenti, obyekt kolleksiyalarini panjaralar, roʻyxatlar va maxsus maketlar koʻrinishida boshqaradi. UITableView-dan farqli ravishda, UICollectionView bitta ustun bilan cheklanmaydi: UICollectionViewLayout orqali elementlarni ixtiyoriy joylashtirishni qoʻllab-quvvatlaydi. UICollectionView mohiyatini, FlowLayout va CompositionalLayout qanday ishlashini va Swift-da maxsus hujayralar yaratishni tushuntiramiz. IT Sectr-da UICollectionView-dan galereyalar, kataloglar va eʼlonlar taxtalari uchun foydalanamiz. Jadvallar bilan solishtirish uchun UITableView haqidagi maqolani oʻqing.
Asosiy nuqtalar
UICollectionView — iOS 6 (2012) da taqdim etilgan UIKit freymvorkidan sinf. UICollectionViewLayout obyekti boshqaradigan moslashuvchan maketda tartiblangan hujayralar (UICollectionViewCell) kolleksiyasini koʻrsatadi. UICollectionView UITableView bilan bir xil vazifani (roʻyxatlar) hal qiladi, lekin elementlarni ixtiyoriy joylashtirish bilan: panjaralar, karusellar, mozaikalar, kaskadlar.
Arxitektura UICollectionView MVC andozasi asosida qurilgan: maʼlumotlar — DataSource-da, maket — UICollectionViewLayout-da, xatti-harakat — UICollectionViewDelegate-da. Bu boʻlinish maʼlumot kodini oʻzgartirmasdan maketlarni almashtirish imkonini beradi. Apple maʼlumotlariga koʻra (WWDC 2025), App Store top 100 dan 72% iOS ilovalari kontentni koʻrsatish uchun UICollectionView-dan foydalanadi. CollectionView iOS 6 dan koʻp ustunli maketlarni qoʻllab-quvvatlaydi, iOS 13 dan esa murakkab boʻlimlar uchun CompositionalLayout oldi.
UICollectionView UITableView kabi qayta ishlatiladigan hujayralar hovuzidan (reuse queue) foydalanadi. dequeueReusableCell(withReuseIdentifier:for:) metodi hovuzdan hujayra qaytaradi yoki hovuz boʻsh boʻlsa yangisini yaratadi. UITableView-dan farqli ravishda, UICollectionViewCell hujayrasi ichki contentView-ga ega, unga barcha subview-lar qoʻshilishi kerak — ularni toʻgʻridan-toʻgʻri hujayraga qoʻshmang, chunki contentView tanlash va tahrirlash animatsiyasi uchun javobgardir.
UICollectionViewFlowLayout — iOS 6 dan ishlaydigan standart maket. Elementlarni qatorlar boʻylab (flow) joylashtiradi, hujayra oʻlchami, aylantirish yoʻnalishi, minimal intervallar va boʻlimlarni sozlash imkoniyati bilan. UICollectionViewCompositionalLayout — maketni bloklar kombinatsiyasi orqali tavsiflaydigan zamonaviy maket (iOS 13+): guruh → boʻlim → maket, bu yerda har bir guruh gorizontal, vertikal yoki maxsus boʻlishi mumkin.
| Parametr | UICollectionViewFlowLayout | UICollectionViewCompositionalLayout |
|---|---|---|
| Minimal versiya | iOS 6 | iOS 13 |
| Murakkab maketlar | Faqat oddiy panjara yoki roʻyxat | Turli maketli boʻlimlar, guruhlar, karusellar |
| Moslashuvchanlik | Delegat hajmi orqali | NSCollectionLayoutDimension.fractionalWidth/Height |
| Unumdorlik | Barcha koʻrinadigan elementlarni renderlaydi | Dangasa boʻlim yaratish |
| iPad qoʻllab-quvvatlashi | Qoʻlda moslashtirish talab qiladi | fractionalWidth orqali moslashuvchan guruhlar |
| Yozish murakkabligi | Past (5–10 qator) | Oʻrta (15–30 qator) |
// FlowLayout bilan asosiy UICollectionView
class ViewController: UIViewController {
private var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumInteritemSpacing = 8
layout.minimumLineSpacing = 12
layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
layout.itemSize = CGSize(width: view.frame.width - 32, height: 100)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "cell")
collectionView.dataSource = self
view.addSubview(collectionView)
}
}
// DataSource
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int { 20 }
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
as! CustomCell
cell.configure(with: "Item \(indexPath.row)")
return cell
}
}
Apple tavsiyasi (WWDC 2025): yangi loyihalar uchun CompositionalLayout-dan foydalaning. Moslashuvchan maketlar uchun koʻproq imkoniyatlar beradi, UIKit va SwiftUI bilan UICollectionView.Representable orqali yaxshiroq ishlaydi va avtomatik oʻlchamli boʻlim sarlavhalarini qoʻllab-quvvatlaydi. FlowLayout-ni bir xil hujayralardan iborat oddiy panjara ekranlari va iOS 12 va undan past minimal versiya uchun qoldiring.
UICollectionViewCell — UICollectionView hujayralari uchun asosiy sinf. Har bir hujayra contentView (asosiy konteyner), backgroundView (standart fon), selectedBackgroundView (tanlashda fon) ni oʻz ichiga oladi. Hujayra koʻrinishini contentView ichida sozlang — hech qachon subview-larni toʻgʻridan-toʻgʻri UICollectionViewCell-ga qoʻshmang.
// Konfiguratsiya bilan maxsus hujayra
class ProductCell: UICollectionViewCell {
private let imageView = UIImageView()
private let titleLabel = UILabel()
private let priceLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupViews() {
contentView.addSubview(imageView)
contentView.addSubview(titleLabel)
contentView.addSubview(priceLabel)
// Auto Layout constraints
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: contentView.topAnchor),
imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
titleLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 8),
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8),
priceLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4),
priceLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8)
])
}
func configure(with product: Product) {
imageView.image = UIImage(named: product.imageName)
titleLabel.text = product.title
priceLabel.text = product.price
}
}
UICollectionViewDelegate tanlash, ajratib koʻrsatish, kontekst menyulari va qayta tartiblash uchun metodlarni taqdim etadi. UITableView-dan farqli ravishda, UICollectionViewDelegate nafaqat elementni bosishni, balki uzoq bosishni ham (UIContextMenuInteraction orqali kontekst menyusi) boshqarish imkonini beradi. Bosishni boshqarish uchun collectionView(_:didSelectItemAt:) ni implement qiling — tanlash animatsiyasi tugagach chaqiriladi.
UICollectionViewDiffableDataSource — iOS 13 da taqdim etilgan UICollectionViewDataSource-ning tip-xavfsiz oʻrnini bosuvchi. cellForItemAt orqali qoʻlda boshqarish oʻrniga, DiffableDataSource NSDiffableDataSourceSnapshot-dan foydalanadi — eski va yangi holat oʻrtasidagi farqni avtomatik hisoblaydigan va oʻzgarishlarni animatsiya qiladigan maʼlumot holati surati.
// Boʻlimlar bilan DiffableDataSource
enum Section {
case featured, recommended, categories
}
class ModernDataSource: UIViewController {
private var dataSource: UICollectionViewDiffableDataSource<Section, Product>!
override func viewDidLoad() {
super.viewDidLoad()
configureDataSource()
applyInitialSnapshot()
}
private func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<ProductCell, Product> { cell, _, product in
cell.configure(with: product)
}
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) {
collectionView, indexPath, product in
collectionView.dequeueConfiguredReusableCell(
using: cellRegistration, for: indexPath, item: product
)
}
}
private func applyInitialSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Product>()
snapshot.appendSections([.featured, .recommended, .categories])
snapshot.appendItems(featuredProducts, toSection: .featured)
snapshot.appendItems(recommendedProducts, toSection: .recommended)
snapshot.appendItems(categories, toSection: .categories)
dataSource.apply(snapshot, animatingDifferences: true)
}
// Avtomatik animatsiya bilan yangilash
func updateProducts(_ products: [Product]) {
var snapshot = dataSource.snapshot()
snapshot.deleteItems(snapshot.itemIdentifiers)
snapshot.appendItems(products)
dataSource.apply(snapshot, animatingDifferences: true)
}
}
DiffableDataSource afzalliklari: (1) avtomatik animatsiya — insert, delete, reload standart animatsiya bilan sodir boʻladi; (2) tip xavfsizligi — boʻlimlar va elementlar tiplashtirilgan, runtime xatosi oʻrniga kompilyatsiya xatosi; (3) Snapshot — holat suratini saqlash, bekor qilish, solishtirish mumkin; (4) unumdorlik — DiffableDataSource minimal oʻzgarishlar toʻplamini hisoblash uchun Hellir algoritmidan foydalanadi. Apple (WWDC 2024) barcha yangi UICollectionView-lar uchun DiffableDataSource-ni tavsiya qiladi, eski DataSource-ni faqat iOS 12 va undan eski versiyalar uchun qoldiring.
UICollectionViewLayout — kolleksiya elementlarining joylashuvini toʻliq boshqaradigan mavhum sinf. Agar FlowLayout va CompositionalLayout mos kelmasa (masalan, doiraviy maket, spiral, diagramma), UICollectionViewLayout-ning osti sinfini yarating va maket tayyorlash metodlarini override qiling.
// Maxsus doiraviy maket
class CircularLayout: UICollectionViewLayout {
private var attributesCache: [UICollectionViewLayoutAttributes] = []
private let radius: CGFloat = 120
override func prepare() {
super.prepare()
attributesCache.removeAll()
guard let collectionView else { return }
let count = collectionView.numberOfItems(inSection: 0)
let center = CGPoint(x: collectionView.bounds.midX, y: collectionView.bounds.midY)
for i in 0..<count {
let indexPath = IndexPath(item: i, section: 0)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
let angle = (CGFloat(i) / CGFloat(count)) * 2 * .pi
attributes.center = CGPoint(
x: center.x + radius * cos(angle),
y: center.y + radius * sin(angle)
)
attributes.size = CGSize(width: 60, height: 60)
attributesCache.append(attributes)
}
}
override var collectionViewContentSize: CGSize {
collectionView?.bounds.size ?? .zero
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
attributesCache.filter { $0.frame.intersects(rect) }
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
attributesCache[indexPath.item]
}
}
Unumdorlik: maxsus UICollectionViewLayout prepare() da atributlarni keshlashi va layoutAttributesForItem(at:) da O(1) bilan qaytarishi kerak. 1000+ elementli kolleksiyalar uchun shouldInvalidateLayout(forBoundsChange:) orqali inkremental kesh yangilashdan foydalaning — bu aylantirish vaqtida butun maketni qayta hisoblamaslik imkonini beradi. Apple (WWDC 2023) maxsus maketlar oʻrniga CompositionalLayout-ni tavsiya qiladi: u noldan maket yozishga hojat qoldirmasdan stsenariylarning 95% ni qamrab oladi.
UITableView va UICollectionView — roʻyxatlarni koʻrsatish uchun ikkita asosiy UIKit komponenti. UITableView soddaroq va bir ustunli roʻyxatlar uchun moʻljallangan. UICollectionView moslashuvchanroq va istalgan maketlarni qoʻllab-quvvatlaydi. Ularning oʻrtasida tanlov maʼlumotlarning vizual tuzilishiga va talab qilinadigan moslashtirishga bogʻliq.
| Parametr | UITableView | UICollectionView |
|---|---|---|
| Maket | Faqat vertikal roʻyxat | Roʻyxat, panjara, kaskad, karusel, maxsus |
| Murakkablik | Past (oddiy DataSource) | Oʻrta (Layout + DataSource + Delegate) |
| Standart hujayra | 4 uslub (basic, subtitle, value1, value2) | Faqat boʻsh (contentView orqali maxsus) |
| Tahrirlash rejimi | Ichki (delete, move, insert) | Qoʻlda amalga oshirish talab qiladi |
| Header/Footer | Ichki (viewForHeaderInSection) | Yordamchi koʻrinishlar orqali |
| Unumdorlik | Roʻyxatlar uchun yuqori | Istalgan maketlar uchun yuqori |
| iOS 6+ | iOS 2 dan mavjud | iOS 6 dan mavjud |
Amaliy qoida: ekran oddiy qatorlar roʻyxati boʻlsa (sozlamalar, kontaktlar, menyu) UITableView-dan foydalaning. Ekran panjara, gorizontal aylantirish, karusel, turli hujayra oʻlchamlari yoki murakkab guruhlash talab qilsa UICollectionView-dan foydalaning. iOS 14 dan boshlab UITableView ham UICollectionLayoutListConfiguration orqali CompositionalLayout qoʻllab-quvvatlashini oldi, bu ikkala komponentning afzalliklarini birlashtirish imkonini beradi.
Tez-tez beriladigan savollar
UICollectionViewFlowLayout da scrollDirection = .horizontal ni oʻrnating. CompositionalLayout uchun guruhning moslashuvchan kengligi uchun fractionalWidth bilan NSCollectionLayoutSize dan foydalaning. Gorizontal aylantirish karusellar, galereyalar va kategoriyalar uchun yaxshi. Sahifalash uchun collectionView.isPagingEnabled = true ni oʻrnating yoki itemSize = bounds.width bilan UICollectionViewFlowLayout dan foydalaning.
Tekshiring: (1) hujayra register(_:forCellWithReuseIdentifier:) orqali roʻyxatdan oʻtgan, (2) DataSource elementlar sonini > 0 qaytaradi, (3) hujayra toʻgʻri reuseIdentifier bilan dequeued qilingan, (4) itemSize nolga teng emas (FlowLayout uchun). Odatiy xato — itemSize = CGSize.zero, bunda hujayralar nol balandlikka ega boʻladi. itemSize-ni aniq belgilang yoki collectionView(_:layout:sizeForItemAt:) delegatini implement qiling.
FlowLayout uchun: layout.minimumInteritemSpacing (qatordagi elementlar orasida) va layout.minimumLineSpacing (qatorlar orasida). CompositionalLayout uchun: NSCollectionLayoutGroup.interItemSpacing va guruh/boʻlimda contentInsets. sectionInset boʻlimning tashqi boʻshliqlarini belgilaydi. Safe Area ni toʻgʻri hisobga olish uchun sectionInsetReference = .fromContentInset dan foydalaning.
Guruh animatsiyalari uchun performBatchUpdates dan foydalaning: collectionView.performBatchUpdates { insertItems, deleteItems, reloadItems }. Xavfsiz va animatsiyali yangilash uchun UICollectionViewDiffableDataSource dan foydalaning: dataSource.apply(snapshot, animatingDifferences: true) ni chaqiring — barcha oʻzgarishlar avtomatik hisoblanadi va qoʻlda insert/delete holda qoʻllanadi.
SwiftUI da UICollectionView ning analogi LazyVGrid va LazyHGrid (iOS 14+). SwiftUI Grid yozish uchun soddaroq (deklarativ sintaksis), lekin 500+ element va maket moslashtirish uchun UICollectionView dan past. Murakkab kolleksiyalar uchun UIViewRepresentable orqali UICollectionView dan foydalaning. IT Sectr loyihalarida kataloglar va galereyalar uchun UICollectionView, oddiy ekranlar uchun SwiftUI Grid ni tanlaymiz.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.