UICollectionView — essentie, collecties en FlowLayout in iOS

Auteur: IT Sectr Gepubliceerd: 2026-02-23 Leestijd: 9 min

UICollectionView — een krachtige UIKit-component voor iOS die het weergeven van objectcollecties in de vorm van rasters, lijsten en aangepaste layouts beheert. In tegenstelling tot UITableView is UICollectionView niet beperkt tot één kolom: het ondersteunt willekeurige plaatsing van elementen via UICollectionViewLayout. We leggen de essentie van UICollectionView uit, hoe FlowLayout en CompositionalLayout werken, en hoe u aangepaste cellen in Swift maakt. Bij IT Sectr gebruiken we UICollectionView voor galerijen, catalogi en prikborden. Voor vergelijking met tabellen lees het artikel over UITableView.

Belangrijkste punten

  • UICollectionView — UIKit-component voor het weergeven van collecties in de vorm van rasters, lijsten en willekeurige layouts.
  • UICollectionViewFlowLayout — standaard layout met ondersteuning voor richting, celgroottes en tussenruimtes.
  • UICollectionViewCompositionalLayout — moderne layout (iOS 13+) voor complexe secties met blokken, carrousels en groepen.
  • UICollectionViewDiffableDataSource — type-veilige DataSource met automatische berekening van wijzigingen (iOS 13+).
  • UICollectionViewCell — basis cel met ingebouwde backgroundView, selectedBackgroundView en contentView.

Wat is UICollectionView in iOS?

UICollectionView — is een klasse uit het UIKit-framework, geïntroduceerd in iOS 6 (2012). Het toont een geordende collectie cellen (UICollectionViewCell) in een flexibele layout die wordt beheerd door een UICollectionViewLayout-object. UICollectionView lost dezelfde taak op als UITableView (lijsten), maar met willekeurige plaatsing van elementen: rasters, carrousels, mozaïeken, cascades.

Architectuur van UICollectionView is gebouwd op het MVC-patroon: gegevens — in DataSource, layout — in UICollectionViewLayout, gedrag — in UICollectionViewDelegate. Deze scheiding maakt het mogelijk om layouts te wisselen zonder de gegevenscode te wijzigen. Volgens Apple (WWDC 2025) gebruikt 72% van de iOS-apps in de top 100 van de App Store UICollectionView voor het weergeven van inhoud. CollectionView ondersteunt multi-kolom layouts vanaf iOS 6, en vanaf iOS 13 kreeg het CompositionalLayout voor complexe secties.

Levenscyclus van een cel

UICollectionView gebruikt een pool van herbruikbare cellen (reuse queue), vergelijkbaar met UITableView. De methode dequeueReusableCell(withReuseIdentifier:for:) retourneert een cel uit de pool of maakt een nieuwe aan als de pool leeg is. In tegenstelling tot UITableView heeft de UICollectionViewCell een ingebouwde contentView waaraan alle subviews moeten worden toegevoegd — voeg ze niet rechtstreeks aan de cel toe, omdat contentView verantwoordelijk is voor de juiste animatie van selectie en bewerking.

FlowLayout vs CompositionalLayout: vergelijking

UICollectionViewFlowLayout — standaard layout die werkt vanaf iOS 6. Het plaatst elementen in rijen (flow) met de mogelijkheid om celgrootte, scrollrichting, minimale tussenruimtes en secties in te stellen. UICollectionViewCompositionalLayout — moderne layout (iOS 13+) die de layout beschrijft door een combinatie van blokken: groep → sectie → layout, waarbij elke groep horizontaal, verticaal of aangepast kan zijn.

ParameterUICollectionViewFlowLayoutUICollectionViewCompositionalLayout
Minimale versieiOS 6iOS 13
Complexe layoutsAlleen eenvoudig raster of lijstSecties met verschillende layouts, groepen, carrousels
AanpasbaarheidVia gedelegeerde grootteNSCollectionLayoutDimension.fractionalWidth/Height
PrestatiesRenderet alle zichtbare elementenLazy aanmaken van secties
iPad-ondersteuningVereist handmatige aanpassingAanpasbare groepen via fractionalWidth
SchrijfcomplexiteitLaag (5–10 regels)Gemiddeld (15–30 regels)
swift
// Basis UICollectionView met 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
    }
}

Aanbeveling van Apple (WWDC 2025): gebruik CompositionalLayout voor nieuwe projecten. Het biedt meer mogelijkheden voor aanpasbare layouts, werkt beter met UIKit en SwiftUI via UICollectionView.Representable, en ondersteunt sectiekopjes met automatische grootte. Laat FlowLayout voor eenvoudige schermen met een raster van identieke cellen en minimale versie iOS 12 en lager.

UICollectionViewCell en UICollectionViewDelegate

UICollectionViewCell — de basisklasse voor UICollectionView-cellen. Elke cel bevat contentView (hoofdcontainer), backgroundView (standaard achtergrond), selectedBackgroundView (achtergrond bij selectie). Pas het uiterlijk van de cel aan binnen contentView — voeg nooit subviews rechtstreeks toe aan UICollectionViewCell.

swift
// Aangepaste cel met configuratie
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 biedt methoden voor het afhandelen van selectie, markering, contextmenu's en herordening. In tegenstelling tot UITableView kan UICollectionViewDelegate niet alleen het klikken op een element beheren, maar ook lang indrukken (contextmenu via UIContextMenuInteraction). Implementeer collectionView(_:didSelectItemAt:) voor het afhandelen van klikken — het wordt aangeroepen na voltooiing van de selectie-animatie.

UICollectionViewDiffableDataSource: moderne DataSource

UICollectionViewDiffableDataSource — type-veilige vervanging van UICollectionViewDataSource, geïntroduceerd in iOS 13. In plaats van handmatig cellen beheren via cellForItemAt, gebruikt DiffableDataSource NSDiffableDataSourceSnapshot — een momentopname van de gegevensstatus die automatisch het verschil tussen oude en nieuwe status berekent en wijzigingen animeert.

swift
// DiffableDataSource met secties
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)
    }

    // Update met automatische animatie
    func updateProducts(_ products: [Product]) {
        var snapshot = dataSource.snapshot()
        snapshot.deleteItems(snapshot.itemIdentifiers)
        snapshot.appendItems(products)
        dataSource.apply(snapshot, animatingDifferences: true)
    }
}

Voordelen van DiffableDataSource: (1) automatische animatie — insert, delete, reload gebeuren met standaard animatie; (2) type-veiligheid — secties en elementen zijn getypeerd, compilatiefouten in plaats van runtime-fouten; (3) Snapshot — momentopname kan worden opgeslagen, teruggedraaid, vergeleken; (4) prestaties — DiffableDataSource gebruikt het Hellir-algoritme voor het berekenen van de minimale set wijzigingen. Apple (WWDC 2024) beveelt DiffableDataSource aan voor alle nieuwe UICollectionViews, en laat de oude DataSource alleen voor iOS 12 en ouder.

Een aangepaste layout maken via UICollectionViewLayout

UICollectionViewLayout — abstracte klasse die de plaatsing van collectie-elementen volledig controleert. Als FlowLayout en CompositionalLayout niet geschikt zijn (bijvoorbeeld cirkelvormige layout, spiraal, diagram), maak dan een subklasse van UICollectionViewLayout en overschrijf de methoden voor layoutvoorbereiding.

swift
// Aangepaste cirkelvormige layout
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]
    }
}

Prestaties: aangepaste UICollectionViewLayout moet attributen cachen in prepare() en ze retourneren in O(1) in layoutAttributesForItem(at:). Gebruik voor collecties met 1000+ elementen incrementele cache-update via shouldInvalidateLayout(forBoundsChange:) — dit voorkomt dat de hele layout opnieuw wordt berekend tijdens scrollen. Apple (WWDC 2023) beveelt CompositionalLayout aan in plaats van aangepaste layouts: het dekt 95% van de scenario's zonder dat u een layout vanaf nul hoeft te schrijven.

UICollectionView vs UITableView: wat kies je wanneer

UITableView en UICollectionView — twee belangrijkste UIKit-componenten voor het weergeven van lijsten. UITableView is eenvoudiger en bedoeld voor lijsten met één kolom. UICollectionView is flexibeler en ondersteunt elke layout. De keuze tussen hen hangt af van de visuele structuur van de gegevens en de vereiste aanpassing.

ParameterUITableViewUICollectionView
LayoutAlleen verticale lijstLijst, raster, cascade, carrousel, aangepast
ComplexiteitLaag (eenvoudige DataSource)Gemiddeld (Layout + DataSource + Delegate)
Standaard cel4 stijlen (basic, subtitle, value1, value2)Alleen leeg (aangepast via contentView)
BewerkingsmodusIngebouwd (delete, move, insert)Vereist handmatige implementatie
Header/FooterIngebouwd (viewForHeaderInSection)Via aanvullende weergaven
PrestatiesHoog voor lijstenHoog voor elke layout
iOS 6+Beschikbaar vanaf iOS 2Beschikbaar vanaf iOS 6

Praktische regel: gebruik UITableView als het scherm een eenvoudige lijst met rijen is (instellingen, contacten, menu). Gebruik UICollectionView als het scherm een raster, horizontaal scrollen, carrousel, verschillende celgroottes of complexe groepering vereist. Vanaf iOS 14 heeft UITableView ook ondersteuning gekregen voor CompositionalLayout via UICollectionLayoutListConfiguration, waarmee de voordelen van beide componenten kunnen worden gecombineerd.

Veelgestelde vragen

Hoe maak je een UICollectionView met horizontaal scrollen?

Stel scrollDirection = .horizontal in in UICollectionViewFlowLayout. Gebruik voor CompositionalLayout NSCollectionLayoutSize met fractionalWidth voor aanpasbare groepsbreedte. Horizontaal scrollen is goed voor carrousels, galerijen en categorieën. Stel voor paginascrollen collectionView.isPagingEnabled = true in of gebruik UICollectionViewFlowLayout met itemSize = bounds.width.

Waarom geeft UICollectionView geen cellen weer?

Controleer: (1) cel is geregistreerd via register(_:forCellWithReuseIdentifier:), (2) DataSource retourneert aantal elementen > 0, (3) cel is gedequeued met correcte reuseIdentifier, (4) itemSize is niet nul (voor FlowLayout). Typische fout — itemSize = CGSize.zero, waarbij cellen een hoogte van nul hebben. Stel itemSize expliciet in of implementeer de gedelegeerde collectionView(_:layout:sizeForItemAt:).

Hoe voeg je tussenruimtes toe tussen UICollectionView-cellen?

Voor FlowLayout: layout.minimumInteritemSpacing (tussen elementen in een rij) en layout.minimumLineSpacing (tussen rijen). Voor CompositionalLayout: NSCollectionLayoutGroup.interItemSpacing en contentInsets op groep/sectie. sectionInset stelt de externe tussenruimtes van de sectie in. Gebruik sectionInsetReference = .fromContentInset voor correcte verwerking van de Safe Area.

Hoe werk je UICollectionView bij zonder herladen?

Gebruik performBatchUpdates voor groepsanimaties: collectionView.performBatchUpdates { insertItems, deleteItems, reloadItems }. Gebruik voor veilige en geanimeerde updates UICollectionViewDiffableDataSource: roep dataSource.apply(snapshot, animatingDifferences: true) aan — alle wijzigingen worden automatisch berekend en toegepast zonder handmatige insert/delete.

UICollectionView vs CollectionView in SwiftUI?

In SwiftUI is het equivalent van UICollectionView LazyVGrid en LazyHGrid (iOS 14+). SwiftUI Grid is eenvoudiger te schrijven (declaratieve syntax), maar presteert minder dan UICollectionView voor 500+ elementen en layout-aanpassing. Gebruik voor complexe collecties UICollectionView via UIViewRepresentable. In IT Sectr-projecten kiezen we UICollectionView voor catalogi en galerijen, SwiftUI Grid voor eenvoudige schermen.

Samenvatting

  • UICollectionView — flexibele UIKit-component voor rasters, lijsten, carrousels en aangepaste layouts (iOS 6+).
  • FlowLayout is geschikt voor eenvoudige rasters; CompositionalLayout (iOS 13+) voor complexe secties met verschillende layouts.
  • UICollectionViewCell gebruikt contentView voor alle subviews — voeg ze niet rechtstreeks aan de cel toe.
  • UICollectionViewDiffableDataSource — moderne type-veilige DataSource met automatische animatie van wijzigingen.
  • Aangepaste UICollectionViewLayout maakt het mogelijk om willekeurige layouts te maken (cirkel, spiraal, diagram).
  • 72% van de iOS-apps in de top 100 van de App Store gebruikt UICollectionView voor het weergeven van inhoud.
  • Gebruik UITableView voor eenvoudige lijsten; voor al het andere — UICollectionView.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook