How to Implement a Custom Section in SectionKit: Complete Protocol Guide
To implement a custom section in SectionKit, create a Swift class conforming to SKCSectionProtocol, implement the required properties sectionInjection, safeSizeProvider, and itemCount, register your cell classes in config(sectionView:), and handle cell dequeuing and configuration in item(at:).
SectionKit by linhay provides a protocol-oriented architecture for managing UICollectionView sections as independent, reusable components. When the built-in SKCSingleTypeSection is insufficient for heterogeneous cells or custom layout logic, you must implement a custom section by conforming to the framework's core protocols. The source code in [Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift](https://github.com/linhay/sectionkit/blob/main/Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift) defines the contract your implementation must satisfy.
Understanding the Core Protocols
SectionKit treats every logical block of a collection view as a section. The protocol hierarchy consists of:
SKCBaseSectionProtocol– Bundles data-source, delegate, and action handling capabilities.SKCSectionProtocol– Extends the base protocol to addUICollectionViewDelegateFlowLayoutsupport andSKCAnySectionProtocolconformance.
For most custom implementations, conform directly to SKCSectionProtocol. This protocol provides default implementations for many helper methods through extensions in SKCDataSourceProtocol, allowing you to override only the specific behaviors you need to customize.
Required Components for a Custom Section
Every custom section must provide specific properties and methods that the SKCManager uses to render content:
sectionInjection– A variable of typeSKCSectionInjection?that the manager sets automatically to provide context about the section's position and collection view.safeSizeProvider– A lazy-initializedSKSafeSizeProviderthat supplies size constraints forpreferredSizecalculations. Initialize usingdefaultSafeSizeProviderfor standard behavior.itemCount– An integer property returning the number of rows in the section.config(sectionView:)– A method where you register all cell classes and supplementary views with the collection view using theregister()helper.item(at:)– A method that dequeues and configures theUICollectionViewCellfor a specific row usingdequeue(at:).
Optional but commonly implemented methods include itemSize(at:) for returning specific sizes per row, and item(selected:) for handling user interactions.
Step-by-Step Implementation Guide
Follow these steps to create a robust custom section capable of handling heterogeneous cell types:
- Create a new Swift file and declare a class conforming to
SKCSectionProtocolandSKSafeSizeProviderProtocol. - Define a data structure (such as an enum) representing the different cell types your section will display.
- Implement required properties:
sectionInjection,safeSizeProvider, anditemCount. - Register cells in
config(sectionView:)for every cell type used in the section. - Configure cells in
item(at:)by switching on your data structure, dequeuing the appropriate cell type, and applying its model. - Provide sizes in
itemSize(at:)if you need per-cell sizing, or rely on the default implementation if your cells useSKLoadViewProtocol.
Complete Heterogeneous Section Example
The repository provides a reference template in [Sources/.agent/skills/sectionui/examples/MixedCellsSectionTemplate.swift](https://github.com/linhay/sectionkit/blob/main/.agent/skills/sectionui/examples/MixedCellsSectionTemplate.swift) demonstrating a section mixing multiple cell types. Below is the implementation pattern:
import SectionUI
import UIKit
final class MyMixedSection: SKCSectionProtocol, SKSafeSizeProviderProtocol {
enum CellType {
case header(HeaderCell.Model)
case item(ItemCell.Model)
case footer(FooterCell.Model)
}
var sectionInjection: SKCSectionInjection?
lazy var safeSizeProvider: SKSafeSizeProvider = defaultSafeSizeProvider
private var cellTypes: [CellType] = []
var itemCount: Int { cellTypes.count }
init(cellTypes: [CellType] = []) {
self.cellTypes = cellTypes
}
func config(sectionView: UICollectionView) {
register(HeaderCell.self)
register(ItemCell.self)
register(FooterCell.self)
}
func itemSize(at row: Int) -> CGSize {
switch cellTypes[row] {
case .header(let model):
return HeaderCell.preferredSize(limit: safeSizeProvider.size, model: model)
case .item(let model):
return ItemCell.preferredSize(limit: safeSizeProvider.size, model: model)
case .footer(let model):
return FooterCell.preferredSize(limit: safeSizeProvider.size, model: model)
}
}
func item(at row: Int) -> UICollectionViewCell {
switch cellTypes[row] {
case .header(let model):
let cell = dequeue(at: row) as HeaderCell
cell.config(model)
return cell
case .item(let model):
let cell = dequeue(at: row) as ItemCell
cell.config(model)
return cell
case .footer(let model):
let cell = dequeue(at: row) as FooterCell
cell.config(model)
return cell
}
}
func item(selected row: Int) {
guard case .item(let model) = cellTypes[row] else { return }
print("Item tapped: \(model.title)")
}
}
Integrating with SKCManager
Once implemented, add your custom section to a collection view via SKCManager. The manager automatically calls config(sectionView:) upon insertion and forwards all data-source and delegate callbacks to your section instance.
import SectionKit
let header = HeaderCell.Model(title: "Welcome")
let items = (1...10).map { ItemCell.Model(title: "Item \($0)", subtitle: nil) }
let footer = FooterCell.Model(text: "End of list")
let cellTypes: [MyMixedSection.CellType] = [
.header(header),
.item(items[0]),
.footer(footer)
]
let mixedSection = MyMixedSection(cellTypes: cellTypes)
let manager = SKCManager(collectionView: collectionView)
manager.append(section: mixedSection)
When to Use SKCSingleTypeSection Instead
If your section uses only one cell type, skip the custom implementation. Use SKCSingleTypeSection defined in [Sources/SectionKit/CollectionSingleTypeSection/Entities/SKCSingleTypeSection.swift](https://github.com/linhay/sectionkit/blob/main/Sources/SectionKit/CollectionSingleTypeSection/Entities/SKCSingleTypeSection.swift), which handles registration and dequeuing automatically.
import SectionKit
let models = ["A", "B", "C"]
let singleSection = SKCSingleTypeSection<MyCell>(models)
manager.append(section: singleSection)
Summary
- Conform to
SKCSectionProtocolto create custom sections with full control over heterogeneous cells and layout. - Implement required properties including
sectionInjection,safeSizeProvider, anditemCountto satisfy the protocol contract. - Register cells in
config(sectionView:)to ensure the collection view can dequeue reusable cells. - Dequeue and configure in
item(at:)using thedequeue(at:)helper method provided by the protocol extensions. - Use
SKCSingleTypeSectionfor homogeneous cell types to avoid boilerplate code. - Reference the template in
Sources/.agent/skills/sectionui/examples/MixedCellsSectionTemplate.swiftfor production-ready patterns.
Frequently Asked Questions
What is the difference between SKCBaseSectionProtocol and SKCSectionProtocol?
SKCBaseSectionProtocol provides the foundational data-source and delegate method signatures required for any section implementation. SKCSectionProtocol extends this base protocol to add UICollectionViewDelegateFlowLayout support and SKCAnySectionProtocol conformance, making it the preferred choice for flow layout-based collection views according to the source in Sources/SectionKit/CollectionBaseProtocol/SKCSectionProtocol.swift.
How does SKCManager communicate with my custom section?
SKCManager maintains a reference to your section through the sectionInjection property, which the manager sets automatically when you append the section using manager.append(section:). This injection provides the section with its context, including the collection view instance, enabling methods like dequeue(at:) and register() to function without manual view management.
Can I skip implementing itemSize(at:) in my custom section?
Yes. While implementing itemSize(at:) allows you to return specific sizes per row, SectionKit provides a default implementation. If your cells conform to SKLoadViewProtocol or you use fixed sizes, the default behavior may suffice. However, for heterogeneous sections with varying cell dimensions or dynamic content, explicit implementation is recommended for accurate layout calculations.
Where should I register supplementary views like headers and footers?
Register supplementary views within the config(sectionView:) method alongside your cell registrations. The protocol extension provides register() methods for both cells and supplementary views. The manager calls config(sectionView:) once when the section is first added to the collection view, ensuring all reusable identifiers are established before any dequeuing occurs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →