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 — 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.
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.
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.
| Parameter | UICollectionViewFlowLayout | UICollectionViewCompositionalLayout |
|---|---|---|
| Minimale versie | iOS 6 | iOS 13 |
| Complexe layouts | Alleen eenvoudig raster of lijst | Secties met verschillende layouts, groepen, carrousels |
| Aanpasbaarheid | Via gedelegeerde grootte | NSCollectionLayoutDimension.fractionalWidth/Height |
| Prestaties | Renderet alle zichtbare elementen | Lazy aanmaken van secties |
| iPad-ondersteuning | Vereist handmatige aanpassing | Aanpasbare groepen via fractionalWidth |
| Schrijfcomplexiteit | Laag (5–10 regels) | Gemiddeld (15–30 regels) |
// 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 — 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.
// 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 — 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.
// 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.
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.
// 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.
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.
| Parameter | UITableView | UICollectionView |
|---|---|---|
| Layout | Alleen verticale lijst | Lijst, raster, cascade, carrousel, aangepast |
| Complexiteit | Laag (eenvoudige DataSource) | Gemiddeld (Layout + DataSource + Delegate) |
| Standaard cel | 4 stijlen (basic, subtitle, value1, value2) | Alleen leeg (aangepast via contentView) |
| Bewerkingsmodus | Ingebouwd (delete, move, insert) | Vereist handmatige implementatie |
| Header/Footer | Ingebouwd (viewForHeaderInSection) | Via aanvullende weergaven |
| Prestaties | Hoog voor lijsten | Hoog voor elke layout |
| iOS 6+ | Beschikbaar vanaf iOS 2 | Beschikbaar 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
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.
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:).
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.
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.
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
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.
Lees ook