Implementing modern collection views
At a glance
| Item |
Summary |
| Purpose |
Catalogs compositional layouts, diffable data sources, lists, outlines, reordering, and cell configurations on UIKit and AppKit. |
| App architecture |
This is a suite of independent demonstrations: each screen/window controller owns its layout, data source, identifiers, and snapshots; selected helpers model dynamic data. |
| Main patterns |
Feature catalog, controller-local composition root, snapshot projection, identifier value objects, and configuration protocols. |
| Project style |
Separate iOS and macOS targets organized by capability, with many intentionally self-contained examples. |
Project structure
Modern Collection Views/
├── Compositional Layout/
│ ├── Basics View Controllers/
│ ├── Advanced Layouts View Controllers/
│ ├── App Samples View Controllers/
│ ├── Cells and Supplementary Views/
│ └── Controllers/
├── Diffable/
├── Lists/
├── Outline/
├── Cell Configurations/
└── AppDelegate.swift
Modern Collection Views Mac/
├── Compositional Layout/
├── Diffable/
└── AppDelegate.swift
Structure observations
- Folders are architectural boundaries by API family, not layers of one application.
- Most examples keep
Section/Item, layout construction, registrations, and initial snapshots beside one controller.
- Model helpers such as
WiFiController, MountainsController, and conference controllers appear only when a demo needs changing or richer data.
Overall architecture
flowchart LR
Catalog["Storyboard/menu catalog"] --> Demo["Feature view or window controller"]
Demo --> Layout["Compositional layout"]
Demo --> Registration["Cell/supplementary registration"]
Demo --> DataSource["Diffable data source"]
Model["Local items or helper controller"] --> Snapshot["Snapshot / section snapshot"]
Snapshot --> DataSource
Layout --> Collection["Collection or table view"]
Registration --> DataSource
DataSource --> Collection
State["Selection, filter, reorder, configuration state"] --> Demo
Demo --> Snapshot
Reference code
Modern Collection Views/Compositional Layout/Basics View Controllers/GridViewController.swift:53 — a typical demo owns registration, diffable data source, and initial snapshot in one feature scope.
private func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<TextCell, Int> { (cell, indexPath, identifier) in
// Populate the cell with our item description.
cell.label.text = "\(identifier)"
cell.contentView.backgroundColor = .cornflowerBlue
cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 1
cell.label.textAlignment = .center
cell.label.font = UIFont.preferredFont(forTextStyle: .title1)
}
dataSource = UICollectionViewDiffableDataSource<Section, Int>(collectionView: collectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, identifier: Int) -> UICollectionViewCell? in
// Return the cell.
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier)
}
// initial data
var snapshot = NSDiffableDataSourceSnapshot<Section, Int>()
snapshot.appendSections([.main])
snapshot.appendItems(Array(0..<94))
dataSource.apply(snapshot, animatingDifferences: false)
}
Interpretation
The repeated controller-local setup is deliberate for a catalog: every example can be read and run independently. A production app could extract factories, but doing so here would obscure the specific layout or data-source concept.
Ownership and state
classDiagram
UIViewController *-- UICollectionView : creates per demo
UIViewController *-- UICollectionViewLayout : creates per demo
UIViewController *-- UICollectionViewDiffableDataSource : retains
UICollectionViewDiffableDataSource *-- NSDiffableDataSourceSnapshot : current identifiers
ReorderableListViewController *-- Dictionary : backingStore source of truth
WiFiSettingsViewController *-- WiFiController : dynamic model helper
CustomConfigurationCell *-- CustomContentConfiguration : applies
CustomContentConfiguration ..|> UIContentConfiguration
CustomContentView ..|> UIContentView
Ownership evidence
Modern Collection Views/Lists/ReorderableListViewController.swift:24 — the reorder sample explicitly distinguishes controller-owned source data from the diffable presentation state.
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
lazy var backingStore: [Section: [Item]] = { initialBackingStore() }()
enum ReorderingMethod: CustomStringConvertible {
case finalSnapshot, collectionDifference
}
var reorderingMethod: ReorderingMethod = .collectionDifference
| Owner |
State |
Relationship |
Mutation authority |
| Each demo controller |
View, layout, registrations, data source, snapshot |
Creates/retains feature graph |
Controller setup and callbacks |
| Reorder demo |
backingStore |
Authoritative ordering |
Diffable reordering transaction handler |
| Dynamic helper controller |
Domain items and simulated changes |
Retained by its screen |
Helper callbacks/actions |
| Custom cell |
Current image/configuration state |
UIKit owns reused cell; cell owns applied config |
updateConfiguration(using:) |
Class and protocol design
| Type family |
Responsibility |
Design note |
| Layout demos |
Define compositional item/group/section geometry |
Usually no domain model needed |
| Diffable/list/outline demos |
Translate stable identifiers into snapshots |
Nested identifier types keep identity policy local |
| Model controllers |
Produce/filter changing data |
Used only where state outlives one snapshot |
| Cell and supplementary views |
Render registered content |
Reused by several layout screens when useful |
| Custom configurations |
Separate configuration value from content view |
Implements UIKit configuration contracts |
The strongest protocol-oriented example is CustomContentConfiguration: UIContentConfiguration paired with CustomContentView: UIContentView. Most other variability uses generic diffable data-source types and closures rather than app-defined protocols.
Access control
| Symbol |
Access |
Verified effect |
Rationale |
Custom-config Section and Item |
file-level private |
Only that demonstration can construct identifiers. |
Identity is feature-local. |
| Custom-config data source/view/helpers |
private |
Setup and reused-view state cannot leak to other demos. |
Protects one controller’s composition graph. |
| Many older demo fields/helpers |
implicit internal |
Target code could access them. |
Examples prioritize side-by-side readability over a library boundary. |
| macOS app’s window-controller fields |
private |
App delegate retains windows without exposing them. |
Lifetime ownership only. |
| Public declarations |
none |
No exported framework surface. |
Both targets are applications. |
Reference code
Modern Collection Views/Cell Configurations/CustomConfigurationViewController.swift:10 — identifier and controller implementation details are fully scoped to this feature.
private enum Section: Hashable {
case main
}
Logic ownership and placement
| Logic |
Owner or folder |
Why it belongs there |
| Layout geometry |
Each layout controller |
Environment and section behavior are demo-specific. |
| Snapshot construction |
Each diffable/list/outline controller |
Controller owns the identifiers and UI event mapping. |
| Reorder reconciliation |
ReorderableListViewController |
Must update authoritative backing data from transactions. |
| Dynamic data simulation/filtering |
Helper controllers |
Separates changing model behavior from cell presentation. |
| State-dependent appearance |
Configuration value/cell/content view |
UIKit asks these objects to update for configuration state. |
Design patterns
| Pattern |
Source evidence |
Purpose or tradeoff |
| Feature-catalog architecture |
Modern Collection Views/AppDelegate.swift:11 |
Groups independent examples under one executable. |
| Controller-local composition root |
Modern Collection Views/Compositional Layout/Basics View Controllers/GridViewController.swift:19 |
Keeps each example self-contained. |
| Snapshot projection |
Modern Collection Views/Diffable/WiFiSettingsViewController.swift:118 |
Rebuilds visible structure from current model state. |
| Backing-store reconciliation |
Modern Collection Views/Lists/ReorderableListViewController.swift:145 |
Persists UI reorder transactions into source data. |
| Configuration protocol |
Modern Collection Views/Cell Configurations/CustomConfigurations.swift:27 |
Makes appearance a replaceable state-derived value. |
Naming conventions
- Controllers name the exact concept:
GridViewController, ReorderableListViewController, and WiFiSettingsViewController.
- Nested
Section, Item, and ItemType types keep diffable identifiers close to their owner.
- Setup methods consistently use
createLayout, configureHierarchy, and configureDataSource.
- macOS counterparts use
WindowController; UIKit counterparts use ViewController.
Architecture takeaways
- Treat a sample catalog as independent feature compositions, not as one layered application.
- Keep stable identity types close to the snapshot owner and separate source data when edits must persist.
- Rebuild snapshots as projections of model state instead of manually synchronizing visible indexes.
- Extract reusable configuration values/views when appearance must respond systematically to cell state.
Source map
| Source file |
Relevant symbols |
Modern Collection Views/Compositional Layout/Basics View Controllers/GridViewController.swift |
Minimal compositional/diffable composition |
Modern Collection Views/Diffable/WiFiSettingsViewController.swift |
Dynamic snapshot projection |
Modern Collection Views/Lists/ReorderableListViewController.swift |
Reorder transaction/backing store |
Modern Collection Views/Outline/EmojiExplorerViewController.swift |
Mixed sections and section snapshots |
Modern Collection Views/Cell Configurations/CustomConfigurations.swift |
Configuration protocol implementation |
Modern Collection Views/Cell Configurations/CustomConfigurationViewController.swift |
Private feature identity/state |
Modern Collection Views Mac/AppDelegate.swift |
macOS window-controller ownership |