UICollectionView — essensen, samlingar och FlowLayout i iOS

Författare: IT Sectr Publicerad: 2026-02-23 Lästid: 9 min

UICollectionView — en kraftfull UIKit-komponent för iOS som hanterar visning av objektsamlingar i form av rutnät, listor och anpassade layouter. Till skillnad från UITableView är UICollectionView inte begränsad till en kolumn: den stöder godtycklig placering av element via UICollectionViewLayout. Vi förklarar essensen av UICollectionView, hur FlowLayout och CompositionalLayout fungerar, och hur man skapar anpassade celler i Swift. På IT Sectr använder vi UICollectionView för gallerier, kataloger och anslagstavlor. För jämförelse med tabeller, läs artikeln om UITableView.

Huvudpunkter

  • UICollectionView — UIKit-komponent för visning av samlingar i form av rutnät, listor och godtyckliga layouter.
  • UICollectionViewFlowLayout — standardlayout med stöd för riktning, cellstorlekar och mellanrum.
  • UICollectionViewCompositionalLayout — modern layout (iOS 13+) för komplexa sektioner med block, karuseller och grupper.
  • UICollectionViewDiffableDataSource — typsäker DataSource med automatisk beräkning av ändringar (iOS 13+).
  • UICollectionViewCell — grundläggande cell med inbyggda backgroundView, selectedBackgroundView och contentView.

Vad är UICollectionView i iOS?

UICollectionView — är en klass från UIKit-ramverket, introducerad i iOS 6 (2012). Den visar en ordnad samling celler (UICollectionViewCell) i en flexibel layout som hanteras av ett UICollectionViewLayout-objekt. UICollectionView löser samma uppgift som UITableView (listor), men med godtycklig placering av element: rutnät, karuseller, mosaiker, kaskader.

Arkitektur UICollectionView är byggd på MVC-mönstret: data — i DataSource, layout — i UICollectionViewLayout, beteende — i UICollectionViewDelegate. Denna separation gör det möjligt att byta layouter utan att ändra datakoden. Enligt Apple (WWDC 2025) använder 72% av iOS-apparna i topp 100 på App Store UICollectionView för att visa innehåll. CollectionView stöder flerkolumnslayouter från iOS 6 och från iOS 13 fick den CompositionalLayout för komplexa sektioner.

Cellens livscykel

UICollectionView använder en pool av återanvändbara celler (reuse queue), liknande UITableView. Metoden dequeueReusableCell(withReuseIdentifier:for:) returnerar en cell från poolen eller skapar en ny om poolen är tom. Till skillnad från UITableView har UICollectionViewCell en inbyggd contentView som alla subviews måste läggas till i — lägg inte till dem direkt i cellen, eftersom contentView ansvarar för korrekt animering av markering och redigering.

FlowLayout vs CompositionalLayout: jämförelse

UICollectionViewFlowLayout — standardlayout som fungerar från iOS 6. Den placerar element i rader (flow) med möjlighet att ställa in cellstorlek, scrollriktning, minimala mellanrum och sektioner. UICollectionViewCompositionalLayout — modern layout (iOS 13+) som beskriver layouten genom kombination av block: grupp → sektion → layout, där varje grupp kan vara horisontell, vertikal eller anpassad.

ParameterUICollectionViewFlowLayoutUICollectionViewCompositionalLayout
Minsta versioniOS 6iOS 13
Komplexa layouterEndast enkelt rutnät eller listaSektioner med olika layouter, grupper, karuseller
AnpassningsbarhetGenom delegerad storlekNSCollectionLayoutDimension.fractionalWidth/Height
PrestandaRenderar alla synliga elementLat skapande av sektioner
iPad-stödKräver manuell anpassningAnpassningsbara grupper via fractionalWidth
SkrivkomplexitetLåg (5–10 rader)Medel (15–30 rader)
swift
// Grundläggande UICollectionView med 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
    }
}

Apples rekommendation (WWDC 2025): för nya projekt använd CompositionalLayout. Det ger fler möjligheter för anpassningsbara layouter, fungerar bättre med UIKit och SwiftUI via UICollectionView.Representable och stöder sektionsrubriker med automatisk storlek. Lämna FlowLayout för enkla skärmar med rutnät av identiska celler och minsta version iOS 12 och lägre.

UICollectionViewCell och UICollectionViewDelegate

UICollectionViewCell — basklass för UICollectionView-celler. Varje cell innehåller contentView (huvudbehållare), backgroundView (standardbakgrund), selectedBackgroundView (bakgrund vid markering). Anpassa cellens utseende inuti contentView — lägg aldrig till subviews direkt i UICollectionViewCell.

swift
// Anpassad cell med konfiguration
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 tillhandahåller metoder för hantering av markering, högdagring, snabbmenyer och omordning. Till skillnad från UITableView kan UICollectionViewDelegate inte bara hantera klick på ett element, utan också långtryckning (snabbmeny via UIContextMenuInteraction). För att hantera klick, implementera collectionView(_:didSelectItemAt:) — den anropas när markeringsanimeringen är klar.

UICollectionViewDiffableDataSource: modern DataSource

UICollectionViewDiffableDataSource — typsäker ersättning för UICollectionViewDataSource, introducerad i iOS 13. Istället för manuell hantering av celler via cellForItemAt använder DiffableDataSource NSDiffableDataSourceSnapshot — en ögonblicksbild av datatillståndet som automatiskt beräknar skillnaden mellan gammalt och nytt tillstånd och animerar ändringarna.

swift
// DiffableDataSource med sektioner
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)
    }

    // Uppdatering med automatisk animering
    func updateProducts(_ products: [Product]) {
        var snapshot = dataSource.snapshot()
        snapshot.deleteItems(snapshot.itemIdentifiers)
        snapshot.appendItems(products)
        dataSource.apply(snapshot, animatingDifferences: true)
    }
}

Fördelar med DiffableDataSource: (1) automatisk animering — insert, delete, reload sker med standardanimering; (2) typsäkerhet — sektioner och element är typade, kompileringsfel istället för runtime-fel; (3) Snapshot — ögonblicksbilden kan sparas, ångras, jämföras; (4) prestanda — DiffableDataSource använder Hellir-algoritmen för att beräkna minsta uppsättning ändringar. Apple (WWDC 2024) rekommenderar DiffableDataSource för alla nya UICollectionView och lämna den gamla DataSource endast för iOS 12 och äldre.

Skapa anpassad layout via UICollectionViewLayout

UICollectionViewLayout — abstrakt klass som helt styr placeringen av samlingselement. Om FlowLayout och CompositionalLayout inte passar (till exempel cirkulär layout, spiral, diagram), skapa en underklass till UICollectionViewLayout och åsidosätt metoderna för layoutförberedelse.

swift
// Anpassad cirkulär 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]
    }
}

Prestanda: anpassad UICollectionViewLayout bör cachelagra attribut i prepare() och returnera dem i O(1) i layoutAttributesForItem(at:). För samlingar med 1000+ element, använd inkrementell cacheuppdatering via shouldInvalidateLayout(forBoundsChange:) — detta gör att du inte behöver räkna om hela layouten vid scrollning. Apple (WWDC 2023) rekommenderar CompositionalLayout istället för anpassade layouter: den täcker 95% av scenarierna utan att behöva skriva en layout från grunden.

UICollectionView vs UITableView: när du väljer vad

UITableView och UICollectionView — två huvudkomponenter i UIKit för visning av listor. UITableView är enklare och avsedd för enkolumniga listor. UICollectionView är mer flexibel och stöder vilken layout som helst. Valet mellan dem beror på den visuella strukturen av data och den anpassning som krävs.

ParameterUITableViewUICollectionView
LayoutEndast vertikal listaLista, rutnät, kaskad, karusell, anpassad
KomplexitetLåg (enkel DataSource)Medel (Layout + DataSource + Delegate)
Standardcell4 stilar (basic, subtitle, value1, value2)Endast tom (anpassad via contentView)
RedigeringslägeInbyggd (delete, move, insert)Kräver manuell implementering
Header/FooterInbyggd (viewForHeaderInSection)Via kompletterande vyer
PrestandaHög för listorHög för alla layouter
iOS 6+Tillgänglig från iOS 2Tillgänglig från iOS 6

Praktisk regel: använd UITableView om skärmen är en enkel lista med rader (inställningar, kontakter, meny). Använd UICollectionView om skärmen kräver ett rutnät, horisontell scrollning, karusell, olika cellstorlekar eller komplex gruppering. Från iOS 14 har UITableView också fått stöd för CompositionalLayout via UICollectionLayoutListConfiguration, vilket gör det möjligt att kombinera fördelarna med båda komponenterna.

Vanliga frågor

Hur gör man en UICollectionView med horisontell scrollning?

Ställ in scrollDirection = .horizontal i UICollectionViewFlowLayout. För CompositionalLayout använd NSCollectionLayoutSize med fractionalWidth för anpassningsbar gruppbredd. Horisontell scrollning är bra för karuseller, gallerier och kategorier. För sidvis scrollning, ställ in collectionView.isPagingEnabled = true eller använd UICollectionViewFlowLayout med itemSize = bounds.width.

Varför visar UICollectionView inga celler?

Kontrollera: (1) cellen är registrerad via register(_:forCellWithReuseIdentifier:), (2) DataSource returnerar antal element > 0, (3) cellen är dequeued med korrekt reuseIdentifier, (4) itemSize är inte noll (för FlowLayout). Typiskt fel — itemSize = CGSize.zero, där celler har noll höjd. Ställ in itemSize explicit eller implementera delegerad collectionView(_:layout:sizeForItemAt:).

Hur lägger man till mellanrum mellan UICollectionView-celler?

För FlowLayout: layout.minimumInteritemSpacing (mellan element i en rad) och layout.minimumLineSpacing (mellan rader). För CompositionalLayout: NSCollectionLayoutGroup.interItemSpacing och contentInsets på grupp/sektion. sectionInset ställer in sektionens yttre mellanrum. Använd sectionInsetReference = .fromContentInset för korrekt hänsyn till Safe Area.

Hur uppdaterar man UICollectionView utan omladdning?

Använd performBatchUpdates för gruppanimeringar: collectionView.performBatchUpdates { insertItems, deleteItems, reloadItems }. För säker och animerad uppdatering, använd UICollectionViewDiffableDataSource: anropa dataSource.apply(snapshot, animatingDifferences: true) — alla ändringar beräknas och tillämpas automatiskt utan manuella insert/delete.

UICollectionView vs CollectionView i SwiftUI?

I SwiftUI är motsvarigheten till UICollectionView LazyVGrid och LazyHGrid (iOS 14+). SwiftUI Grid är enklare att skriva (deklarativ syntax), men är sämre än UICollectionView i prestanda för 500+ element och layoutanpassning. För komplexa samlingar, använd UICollectionView via UIViewRepresentable. I IT Sectr-projekt väljer vi UICollectionView för kataloger och gallerier, SwiftUI Grid för enkla skärmar.

Sammanfattning

  • UICollectionView — flexibel UIKit-komponent för rutnät, listor, karuseller och anpassade layouter (iOS 6+).
  • FlowLayout passar för enkla rutnät; CompositionalLayout (iOS 13+) för komplexa sektioner med olika layouter.
  • UICollectionViewCell använder contentView för alla subviews — lägg inte till dem direkt i cellen.
  • UICollectionViewDiffableDataSource — modern typsäker DataSource med automatisk animering av ändringar.
  • Anpassad UICollectionViewLayout gör det möjligt att skapa godtyckliga layouter (cirkel, spiral, diagram).
  • 72% av iOS-apparna i topp 100 på App Store använder UICollectionView för att visa innehåll.
  • För enkla listor använd UITableView; för allt annat — UICollectionView.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också