UICollectionView — podstata, kolekce a FlowLayout v iOS

Autor: IT Sectr Publikováno: 2026-02-23 Doba čtení: 9 min

UICollectionView — výkonná komponenta UIKit pro iOS, která spravuje zobrazení kolekcí objektů ve formě mřížek, seznamů a vlastních rozvržení. Na rozdíl od UITableView není UICollectionView omezen na jeden sloupec: podporuje libovolné umístění prvků prostřednictvím UICollectionViewLayout. Vysvětlujeme podstatu UICollectionView, jak fungují FlowLayout a CompositionalLayout, a jak vytvářet vlastní buňky ve Swift. V IT Sectr používáme UICollectionView pro galerie, katalogy a nástěnky. Pro srovnání s tabulkami si přečtěte článek o UITableView.

Hlavní body

  • UICollectionView — komponenta UIKit pro zobrazení kolekcí ve formě mřížek, seznamů a libovolných rozvržení.
  • UICollectionViewFlowLayout — standardní rozvržení s podporou směru, velikostí buněk a intervalů.
  • UICollectionViewCompositionalLayout — moderní rozvržení (iOS 13+) pro složité sekce s bloky, kolotoči a skupinami.
  • UICollectionViewDiffableDataSource — typově bezpečný DataSource s automatickým výpočtem změn (iOS 13+).
  • UICollectionViewCell — základní buňka s vestavěnými backgroundView, selectedBackgroundView a contentView.

Co je UICollectionView v iOS?

UICollectionView — je třída z frameworku UIKit, představená v iOS 6 (2012). Zobrazuje uspořádanou kolekci buněk (UICollectionViewCell) v flexibilním rozvržení spravovaném objektem UICollectionViewLayout. UICollectionView řeší stejný úkol jako UITableView (seznamy), ale s libovolným umístěním prvků: mřížky, kolotoče, mozaiky, kaskády.

Architektura UICollectionView je postavena na vzoru MVC: data — v DataSource, rozvržení — v UICollectionViewLayout, chování — v UICollectionViewDelegate. Toto oddělení umožňuje měnit rozvržení bez změny kódu dat. Podle Apple (WWDC 2025) používá 72% iOS aplikací z top 100 App Store UICollectionView pro zobrazení obsahu. CollectionView podporuje více sloupců od iOS 6 a od iOS 13 získal CompositionalLayout pro složité sekce.

Životní cyklus buňky

UICollectionView používá fond znovupoužitelných buněk (reuse queue), podobně jako UITableView. Metoda dequeueReusableCell(withReuseIdentifier:for:) vrací buňku z fondu nebo vytváří novou, pokud je fond prázdný. Na rozdíl od UITableView má buňka UICollectionViewCell vestavěný contentView, do kterého je třeba přidávat všechny subview — nepřidávejte je přímo do buňky, protože contentView je zodpovědný za správnou animaci výběru a úprav.

FlowLayout vs CompositionalLayout: srovnání

UICollectionViewFlowLayout — standardní rozvržení fungující od iOS 6. Uspořádává prvky do řádků (flow) s možností nastavení velikosti buňky, směru posouvání, minimálních intervalů a sekcí. UICollectionViewCompositionalLayout — moderní rozvržení (iOS 13+), které popisuje rozvržení kombinací bloků: skupina → sekce → rozvržení, kde každá skupina může být horizontální, vertikální nebo vlastní.

ParametrUICollectionViewFlowLayoutUICollectionViewCompositionalLayout
Minimální verzeiOS 6iOS 13
Složitá rozvrženíPouze jednoduchá mřížka nebo seznamSekce s různými rozvrženími, skupiny, kolotoče
AdaptabilitaPřes velikost delegátaNSCollectionLayoutDimension.fractionalWidth/Height
VýkonVykresluje všechny viditelné prvkyLíné vytváření sekcí
Podpora iPadVyžaduje ruční adaptaciAdaptivní skupiny přes fractionalWidth
Složitost psaníNízká (5–10 řádků)Střední (15–30 řádků)
swift
// Základní UICollectionView s 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
    }
}

Doporučení Apple (WWDC 2025): pro nové projekty používejte CompositionalLayout. Poskytuje více možností pro adaptivní rozvržení, lépe spolupracuje s UIKit a SwiftUI přes UICollectionView.Representable a podporuje záhlaví sekcí s automatickou velikostí. FlowLayout ponechte pro jednoduché obrazovky s mřížkou identických buněk a minimální verzí iOS 12 a nižší.

UICollectionViewCell a UICollectionViewDelegate

UICollectionViewCell — základní třída pro buňky UICollectionView. Každá buňka obsahuje contentView (hlavní kontejner), backgroundView (výchozí pozadí), selectedBackgroundView (pozadí při výběru). Přizpůsobte vzhled buňky uvnitř contentView — nikdy nepřidávejte subview přímo do UICollectionViewCell.

swift
// Vlastní buňka s konfigurací
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 poskytuje metody pro zpracování výběru, zvýraznění, kontextových nabídek a přeuspořádání. Na rozdíl od UITableView umožňuje UICollectionViewDelegate ovládat nejen kliknutí na prvek, ale také dlouhé stisknutí (kontextová nabídka přes UIContextMenuInteraction). Pro zpracování kliknutí implementujte collectionView(_:didSelectItemAt:) — volá se po dokončení animace výběru.

UICollectionViewDiffableDataSource: moderní DataSource

UICollectionViewDiffableDataSource — typově bezpečná náhrada UICollectionViewDataSource, představená v iOS 13. Místo ručního správy buněk přes cellForItemAt používá DiffableDataSource NSDiffableDataSourceSnapshot — snímek stavu dat, který automaticky vypočítá rozdíl mezi starým a novým stavem a animuje změny.

swift
// DiffableDataSource se sekcemi
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)
    }

    // Aktualizace s automatickou animací
    func updateProducts(_ products: [Product]) {
        var snapshot = dataSource.snapshot()
        snapshot.deleteItems(snapshot.itemIdentifiers)
        snapshot.appendItems(products)
        dataSource.apply(snapshot, animatingDifferences: true)
    }
}

Výhody DiffableDataSource: (1) automatická animace — insert, delete, reload probíhají s výchozí animací; (2) typová bezpečnost — sekce a prvky jsou typované, chyby při kompilaci místo runtime chyb; (3) Snapshot — snímek stavu lze uložit, vrátit, porovnat; (4) výkon — DiffableDataSource používá Hellirův algoritmus pro výpočet minimální sady změn. Apple (WWDC 2024) doporučuje DiffableDataSource pro všechna nová UICollectionView a starý DataSource ponechte pouze pro iOS 12 a starší.

Vytvoření vlastního rozvržení pomocí UICollectionViewLayout

UICollectionViewLayout — abstraktní třída, která zcela řídí rozmístění prvků kolekce. Pokud FlowLayout a CompositionalLayout nevyhovují (například kruhové rozvržení, spirála, diagram), vytvořte podtřídu UICollectionViewLayout a přepište metody přípravy rozvržení.

swift
// Vlastní kruhové rozvržení
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]
    }
}

Výkon: vlastní UICollectionViewLayout by měl ukládat atributy do mezipaměti v prepare() a vracet je v O(1) v layoutAttributesForItem(at:). Pro kolekce s 1000+ prvky používejte inkrementální aktualizaci mezipaměti přes shouldInvalidateLayout(forBoundsChange:) — to umožňuje nepřepočítávat celé rozvržení při posouvání. Apple (WWDC 2023) doporučuje CompositionalLayout místo vlastních rozvržení: pokrývá 95% scénářů bez nutnosti psát rozvržení od nuly.

UICollectionView vs UITableView: kdy co zvolit

UITableView a UICollectionView — dvě hlavní komponenty UIKit pro zobrazení seznamů. UITableView je jednodušší a určený pro jednosloupcové seznamy. UICollectionView je flexibilnější a podporuje jakákoli rozvržení. Výběr mezi nimi závisí na vizuální struktuře dat a požadovaném přizpůsobení.

ParametrUITableViewUICollectionView
RozvrženíPouze vertikální seznamSeznam, mřížka, kaskáda, kolotoč, vlastní
SložitostNízká (jednoduchý DataSource)Střední (Layout + DataSource + Delegate)
Výchozí buňka4 styly (basic, subtitle, value1, value2)Pouze prázdná (vlastní přes contentView)
Režim úpravVestavěný (delete, move, insert)Vyžaduje ruční implementaci
Header/FooterVestavěné (viewForHeaderInSection)Přes doplňkové pohledy
VýkonVysoký pro seznamyVysoký pro jakákoli rozvržení
iOS 6+Dostupný od iOS 2Dostupný od iOS 6

Praktické pravidlo: použijte UITableView pokud je obrazovka jednoduchý seznam řádků (nastavení, kontakty, menu). Použijte UICollectionView pokud obrazovka vyžaduje mřížku, horizontální posouvání, kolotoč, různé velikosti buněk nebo složité seskupování. Od iOS 14 získala také UITableView podporu CompositionalLayout přes UICollectionLayoutListConfiguration, což umožňuje kombinovat výhody obou komponent.

Často kladené otázky

Jak vytvořit UICollectionView s horizontálním posouváním?

Nastavte scrollDirection = .horizontal v UICollectionViewFlowLayout. Pro CompositionalLayout použijte NSCollectionLayoutSize s fractionalWidth pro adaptivní šířku skupiny. Horizontální posouvání je vhodné pro kolotoče, galerie a kategorie. Pro stránkové posouvání nastavte collectionView.isPagingEnabled = true nebo použijte UICollectionViewFlowLayout s itemSize = bounds.width.

Proč UICollectionView nezobrazuje buňky?

Zkontrolujte: (1) buňka je zaregistrována přes register(_:forCellWithReuseIdentifier:), (2) DataSource vrací počet prvků > 0, (3) buňka byla dequeued se správným reuseIdentifier, (4) itemSize není nulový (pro FlowLayout). Typická chyba — itemSize = CGSize.zero, při kterém mají buňky nulovou výšku. Nastavte itemSize explicitně nebo implementujte delegáta collectionView(_:layout:sizeForItemAt:).

Jak přidat mezery mezi buňkami UICollectionView?

Pro FlowLayout: layout.minimumInteritemSpacing (mezi prvky v řádku) a layout.minimumLineSpacing (mezi řádky). Pro CompositionalLayout: NSCollectionLayoutGroup.interItemSpacing a contentInsets na skupině/sekcí. sectionInset nastavuje vnější mezery sekce. Použijte sectionInsetReference = .fromContentInset pro správné zohlednění Safe Area.

Jak aktualizovat UICollectionView bez opětovného načtení?

Použijte performBatchUpdates pro skupinové animace: collectionView.performBatchUpdates { insertItems, deleteItems, reloadItems }. Pro bezpečnou a animovanou aktualizaci použijte UICollectionViewDiffableDataSource: zavolejte dataSource.apply(snapshot, animatingDifferences: true) — všechny změny se automaticky vypočítají a aplikují bez ručních insert/delete.

UICollectionView vs CollectionView ve SwiftUI?

Ve SwiftUI je analogií UICollectionView LazyVGrid a LazyHGrid (iOS 14+). SwiftUI Grid je jednodušší na psaní (deklarativní syntaxe), ale zaostává za UICollectionView ve výkonu pro 500+ prvků a přizpůsobení rozvržení. Pro složité kolekce použijte UICollectionView přes UIViewRepresentable. V projektech IT Sectr volíme UICollectionView pro katalogy a galerie, SwiftUI Grid pro jednoduché obrazovky.

Shrnutí

  • UICollectionView — flexibilní komponenta UIKit pro mřížky, seznamy, kolotoče a vlastní rozvržení (iOS 6+).
  • FlowLayout je vhodný pro jednoduché mřížky; CompositionalLayout (iOS 13+) pro složité sekce s různými rozvrženími.
  • UICollectionViewCell používá contentView pro všechny subview — nepřidávejte je přímo do buňky.
  • UICollectionViewDiffableDataSource — moderní typově bezpečný DataSource s automatickou animací změn.
  • Vlastní UICollectionViewLayout umožňuje vytvářet libovolná rozvržení (kruh, spirála, diagram).
  • 72% iOS aplikací z top 100 App Store používá UICollectionView pro zobrazení obsahu.
  • Pro jednoduché seznamy použijte UITableView; pro vše ostatní — UICollectionView.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také