UICollectionView — esensi, koleksi dan FlowLayout di iOS

Penulis: IT Sectr Diterbitkan: 2026-02-23 Waktu membaca: 9 mnt

UICollectionView — komponen UIKit yang kuat untuk iOS yang mengatur tampilan koleksi objek dalam bentuk grid, daftar, dan tata letak kustom. Berbeda dengan UITableView, UICollectionView tidak terbatas pada satu kolom: ia mendukung penempatan elemen secara arbitrer melalui UICollectionViewLayout. Menjelaskan esensi UICollectionView, cara kerja FlowLayout dan CompositionalLayout, serta cara membuat sel kustom di Swift. Di IT Sectr kami menggunakan UICollectionView untuk galeri, katalog, dan papan pengumuman. Untuk perbandingan dengan tabel, baca artikel tentang UITableView.

Poin utama

  • UICollectionView — komponen UIKit untuk menampilkan koleksi dalam bentuk grid, daftar, dan tata letak arbitrer.
  • UICollectionViewFlowLayout — tata letak standar dengan dukungan arah, ukuran sel, dan jarak.
  • UICollectionViewCompositionalLayout — tata letak modern (iOS 13+) untuk bagian kompleks dengan blok, korsel, dan grup.
  • UICollectionViewDiffableDataSource — DataSource yang aman tipe dengan perhitungan perubahan otomatis (iOS 13+).
  • UICollectionViewCell — sel dasar dengan backgroundView, selectedBackgroundView, dan contentView bawaan.

Apa itu UICollectionView di iOS?

UICollectionView — adalah kelas dari framework UIKit, diperkenalkan di iOS 6 (2012). Kelas ini menampilkan koleksi sel (UICollectionViewCell) yang teratur dalam tata letak fleksibel yang dikelola oleh objek UICollectionViewLayout. UICollectionView menyelesaikan tugas yang sama dengan UITableView (daftar), tetapi dengan penempatan elemen secara arbitrer: grid, korsel, mozaik, kaskade.

Arsitektur UICollectionView dibangun di atas pola MVC: data — di DataSource, tata letak — di UICollectionViewLayout, perilaku — di UICollectionViewDelegate. Pemisahan ini memungkinkan penggantian tata letak tanpa mengubah kode data. Menurut Apple (WWDC 2025), 72% aplikasi iOS di 100 besar App Store menggunakan UICollectionView untuk menampilkan konten. CollectionView mendukung tata letak multi-kolom sejak iOS 6, dan sejak iOS 13 mendapatkan CompositionalLayout untuk bagian kompleks.

Siklus hidup sel

UICollectionView menggunakan kumpulan sel yang dapat digunakan kembali (reuse queue), mirip dengan UITableView. Metode dequeueReusableCell(withReuseIdentifier:for:) mengembalikan sel dari kumpulan atau membuat yang baru jika kumpulan kosong. Berbeda dengan UITableView, sel UICollectionViewCell memiliki contentView bawaan tempat semua subview harus ditambahkan — jangan menambahkannya langsung ke sel, karena contentView bertanggung jawab atas animasi pemilihan dan pengeditan yang benar.

FlowLayout vs CompositionalLayout: perbandingan

UICollectionViewFlowLayout — tata letak standar yang berfungsi sejak iOS 6. Menempatkan elemen dalam baris (flow) dengan kemampuan mengatur ukuran sel, arah gulir, jarak minimum, dan bagian. UICollectionViewCompositionalLayout — tata letak modern (iOS 13+) yang mendeskripsikan tata letak melalui kombinasi blok: grup → bagian → tata letak, di mana setiap grup dapat horizontal, vertikal, atau kustom.

ParameterUICollectionViewFlowLayoutUICollectionViewCompositionalLayout
Versi minimumiOS 6iOS 13
Tata letak kompleksHanya grid atau daftar sederhanaBagian dengan tata letak berbeda, grup, korsel
AdaptabilitasMelalui ukuran delegasiNSCollectionLayoutDimension.fractionalWidth/Height
KinerjaMerender semua elemen yang terlihatPembuatan bagian secara malas
Dukungan iPadMemerlukan adaptasi manualGrup adaptif melalui fractionalWidth
Kompleksitas penulisanRendah (5–10 baris)Sedang (15–30 baris)
swift
// UICollectionView dasar dengan FlowLayout
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
    }
}

Rekomendasi Apple (WWDC 2025): untuk proyek baru gunakan CompositionalLayout. Memberikan lebih banyak kemungkinan untuk tata letak adaptif, bekerja lebih baik dengan UIKit dan SwiftUI melalui UICollectionView.Representable, dan mendukung header bagian dengan ukuran otomatis. Biarkan FlowLayout untuk layar sederhana dengan grid sel identik dan versi minimum iOS 12 ke bawah.

UICollectionViewCell dan UICollectionViewDelegate

UICollectionViewCell — kelas dasar untuk sel UICollectionView. Setiap sel berisi contentView (kontainer utama), backgroundView (latar belakang default), selectedBackgroundView (latar belakang saat dipilih). Sesuaikan tampilan sel di dalam contentView — jangan pernah menambahkan subview langsung ke UICollectionViewCell.

swift
// Sel kustom dengan konfigurasi
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 menyediakan metode untuk menangani pemilihan, penyorotan, menu konteks, dan pengurutan ulang. Berbeda dengan UITableView, UICollectionViewDelegate memungkinkan kontrol tidak hanya klik pada elemen, tetapi juga tekan lama (menu konteks melalui UIContextMenuInteraction). Untuk menangani klik, implementasikan collectionView(_:didSelectItemAt:) — dipanggil setelah animasi pemilihan selesai.

UICollectionViewDiffableDataSource: DataSource modern

UICollectionViewDiffableDataSource — pengganti UICollectionViewDataSource yang aman tipe, diperkenalkan di iOS 13. Alih-alih mengelola sel secara manual melalui cellForItemAt, DiffableDataSource menggunakan NSDiffableDataSourceSnapshot — gambaran status data yang secara otomatis menghitung perbedaan antara status lama dan baru serta menganimasikan perubahan.

swift
// DiffableDataSource dengan bagian
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)
    }

    // Pembaruan dengan animasi otomatis
    func updateProducts(_ products: [Product]) {
        var snapshot = dataSource.snapshot()
        snapshot.deleteItems(snapshot.itemIdentifiers)
        snapshot.appendItems(products)
        dataSource.apply(snapshot, animatingDifferences: true)
    }
}

Keunggulan DiffableDataSource: (1) animasi otomatis — insert, delete, reload terjadi dengan animasi default; (2) keamanan tipe — bagian dan elemen diketik, kesalahan kompilasi alih-alih kesalahan runtime; (3) Snapshot — gambaran status dapat disimpan, dibatalkan, dibandingkan; (4) kinerja — DiffableDataSource menggunakan algoritma Hellir untuk menghitung set perubahan minimum. Apple (WWDC 2024) merekomendasikan DiffableDataSource untuk semua UICollectionView baru, dan DataSource lama hanya untuk iOS 12 dan yang lebih tua.

Membuat tata letak kustom melalui UICollectionViewLayout

UICollectionViewLayout — kelas abstrak yang sepenuhnya mengontrol penempatan elemen koleksi. Jika FlowLayout dan CompositionalLayout tidak cocok (misalnya, tata letak melingkar, spiral, diagram), buat subkelas UICollectionViewLayout dan timpa metode persiapan tata letak.

swift
// Tata letak melingkar kustom
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]
    }
}

Kinerja: UICollectionViewLayout kustom harus menyimpan cache atribut di prepare() dan mengembalikannya dalam O(1) di layoutAttributesForItem(at:). Untuk koleksi dengan 1000+ elemen, gunakan pembaruan cache inkremental melalui shouldInvalidateLayout(forBoundsChange:) — ini memungkinkan untuk tidak menghitung ulang seluruh tata letak saat menggulir. Apple (WWDC 2023) merekomendasikan CompositionalLayout daripada tata letak kustom: mencakup 95% skenario tanpa perlu menulis tata letak dari awal.

UICollectionView vs UITableView: kapan memilih apa

UITableView dan UICollectionView — dua komponen utama UIKit untuk menampilkan daftar. UITableView lebih sederhana dan ditujukan untuk daftar satu kolom. UICollectionView lebih fleksibel dan mendukung tata letak apa pun. Pilihan di antara keduanya tergantung pada struktur visual data dan kustomisasi yang diperlukan.

ParameterUITableViewUICollectionView
Tata letakHanya daftar vertikalDaftar, grid, kaskade, korsel, kustom
KompleksitasRendah (DataSource sederhana)Sedang (Layout + DataSource + Delegate)
Sel default4 gaya (basic, subtitle, value1, value2)Hanya kosong (kustom melalui contentView)
Mode editBawaan (delete, move, insert)Memerlukan implementasi manual
Header/FooterBawaan (viewForHeaderInSection)Melalui tampilan tambahan
KinerjaTinggi untuk daftarTinggi untuk tata letak apa pun
iOS 6+Tersedia sejak iOS 2Tersedia sejak iOS 6

Aturan praktis: gunakan UITableView jika layar adalah daftar baris sederhana (pengaturan, kontak, menu). Gunakan UICollectionView jika layar memerlukan grid, gulir horizontal, korsel, ukuran sel berbeda, atau pengelompokan kompleks. Sejak iOS 14, UITableView juga mendapatkan dukungan CompositionalLayout melalui UICollectionLayoutListConfiguration, yang memungkinkan menggabungkan keunggulan kedua komponen.

Pertanyaan yang sering diajukan

Bagaimana cara membuat UICollectionView dengan gulir horizontal?

Atur scrollDirection = .horizontal di UICollectionViewFlowLayout. Untuk CompositionalLayout gunakan NSCollectionLayoutSize dengan fractionalWidth untuk lebar grup adaptif. Gulir horizontal baik untuk korsel, galeri, dan kategori. Untuk gulir halaman, atur collectionView.isPagingEnabled = true atau gunakan UICollectionViewFlowLayout dengan itemSize = bounds.width.

Mengapa UICollectionView tidak menampilkan sel?

Periksa: (1) sel telah didaftarkan melalui register(_:forCellWithReuseIdentifier:), (2) DataSource mengembalikan jumlah elemen > 0, (3) sel didequeue dengan reuseIdentifier yang benar, (4) itemSize tidak nol (untuk FlowLayout). Kesalahan umum — itemSize = CGSize.zero, yang menyebabkan sel memiliki tinggi nol. Atur itemSize secara eksplisit atau implementasikan delegasi collectionView(_:layout:sizeForItemAt:).

Bagaimana cara menambahkan jarak antar sel UICollectionView?

Untuk FlowLayout: layout.minimumInteritemSpacing (antar elemen dalam satu baris) dan layout.minimumLineSpacing (antar baris). Untuk CompositionalLayout: NSCollectionLayoutGroup.interItemSpacing dan contentInsets pada grup/bagian. sectionInset mengatur jarak eksternal bagian. Gunakan sectionInsetReference = .fromContentInset untuk memperhitungkan Safe Area dengan benar.

Bagaimana cara memperbarui UICollectionView tanpa memuat ulang?

Gunakan performBatchUpdates untuk animasi grup: collectionView.performBatchUpdates { insertItems, deleteItems, reloadItems }. Untuk pembaruan yang aman dan beranimasi, gunakan UICollectionViewDiffableDataSource: panggil dataSource.apply(snapshot, animatingDifferences: true) — semua perubahan akan dihitung dan diterapkan secara otomatis tanpa insert/delete manual.

UICollectionView vs CollectionView di SwiftUI?

Di SwiftUI, padanan UICollectionView adalah LazyVGrid dan LazyHGrid (iOS 14+). SwiftUI Grid lebih sederhana dalam penulisan (sintaks deklaratif), tetapi kalah dari UICollectionView dalam kinerja untuk 500+ elemen dan kustomisasi tata letak. Untuk koleksi kompleks, gunakan UICollectionView melalui UIViewRepresentable. Dalam proyek IT Sectr kami memilih UICollectionView untuk katalog dan galeri, SwiftUI Grid untuk layar sederhana.

Ringkasan

  • UICollectionView — komponen UIKit fleksibel untuk grid, daftar, korsel, dan tata letak kustom (iOS 6+).
  • FlowLayout cocok untuk grid sederhana; CompositionalLayout (iOS 13+) untuk bagian kompleks dengan tata letak berbeda.
  • UICollectionViewCell menggunakan contentView untuk semua subview — jangan menambahkannya langsung ke sel.
  • UICollectionViewDiffableDataSource — DataSource modern yang aman tipe dengan animasi perubahan otomatis.
  • UICollectionViewLayout kustom memungkinkan pembuatan tata letak arbitrer (lingkaran, spiral, diagram).
  • 72% aplikasi iOS di 100 besar App Store menggunakan UICollectionView untuk menampilkan konten.
  • Untuk daftar sederhana gunakan UITableView; untuk sisanya — UICollectionView.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga