Skip to content

Instantly share code, notes, and snippets.

@WillBishop
Last active May 14, 2025 01:29
Show Gist options
  • Save WillBishop/4ee4101c3e1428486a7db4fc04d3cb10 to your computer and use it in GitHub Desktop.
Save WillBishop/4ee4101c3e1428486a7db4fc04d3cb10 to your computer and use it in GitHub Desktop.
Create a UICollectionView with a plain header and grouped content (like Apple Health)
class ViewController: UIViewController {
private lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: createLayout())
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
override func viewDidLoad() {
super.viewDidLoad()
configure()
updateUI()
}
// MARK: CollectionView
func configure() {
collectionView.register(ExampleRow.self, forCellWithReuseIdentifier: "example")
self.view.addSubview(collectionView)
collectionView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
collectionView.topAnchor.constraint(equalTo: self.view.topAnchor),
collectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
])
configureDataSource()
}
func createLayout() -> UICollectionViewCompositionalLayout {
return UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
let configuration = UICollectionLayoutListConfiguration(appearance: Section(rawValue: sectionIndex) == .header ? .plain : .insetGrouped)
return NSCollectionLayoutSection.list(using: configuration, layoutEnvironment: layoutEnvironment)
}
}
// MARK: Data Source
enum Section: Int {
case header
case content
}
enum Item: Hashable {
case row(Int)
}
func configureDataSource() {
self.dataSource = UICollectionViewDiffableDataSource(collectionView: self.collectionView, cellProvider: { collectionView, indexPath, itemIdentifier in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "example", for: indexPath) as! ExampleRow
return cell
})
}
func updateUI() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.header])
snapshot.appendItems([.row(1), .row(2), .row(3)], toSection: .header)
snapshot.appendSections([.content])
snapshot.appendItems([.row(4), .row(5), .row(6)], toSection: .content)
self.dataSource.apply(snapshot)
}
class ExampleRow: UICollectionViewListCell {
override init(frame: CGRect) {
super.init(frame: frame)
let label = UILabel()
label.text = "Hello"
label.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor),
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}
@WillBishop
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment