Can SectionKit Be Used with UICollectionViewFlowLayout? A Complete Guide
Yes, SectionKit fully supports UICollectionViewFlowLayout through dependency injection into SKCollectionView, though you must disable SectionKit's pin plugins when using native flow-layout pinning to prevent debug assertions.
SectionKit is a powerful wrapper framework that simplifies building complex collection views in iOS. While it defaults to a custom SKCollectionFlowLayout, the architecture is layout-agnostic, allowing you to use SectionKit with UICollectionViewFlowLayout or any custom layout subclass while retaining all data-source and section-management features.
How SectionKit Handles Layouts
The framework separates layout concerns from data management through the SKCManager orchestrator, making it compatible with any UICollectionViewLayout implementation.
The Default SKCollectionFlowLayout
When you initialize SKCollectionView without parameters, it automatically creates an internal SKCollectionFlowLayout instance. According to the source in SKCollectionView.swift (lines 37-41), the default initializer constructs this custom layout to enable advanced plugin features like decorations and alignment:
// Default initialization uses SKCollectionFlowLayout
private let collectionView = SKCollectionView() // Uses SKCollectionFlowLayout internally
This default layout powers the full plugin system but is not required for core SectionKit functionality.
Injecting Custom UICollectionViewFlowLayout
You can inject any UICollectionViewLayout subclass by using the frame-based initializer. As implemented in SKCollectionView.swift (lines 42-46), the init(frame:collectionViewLayout:) method accepts custom layouts while still wiring up the SectionKit manager:
let flowLayout = UICollectionViewFlowLayout()
let collectionView = SKCollectionView(
frame: .zero,
collectionViewLayout: flowLayout // Inject custom layout
)
The SKCManager continues to handle section data, cell configuration, and compatible plugins regardless of the underlying layout class.
Code Examples: Using SectionKit with UICollectionViewFlowLayout
Default Configuration
To use SectionKit with its default setup, simply instantiate SKCollectionView. This uses the internal SKCollectionFlowLayout and enables all plugin features:
import SectionUI
class DemoViewController: UIViewController {
private let collectionView = SKCollectionView() // Default SKCollectionFlowLayout
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
// Configure constraints...
// Reload with SectionKit sections
collectionView.manager.reload([
makeSampleSection()
])
}
}
Injecting a Plain Flow Layout
To use a vanilla UICollectionViewFlowLayout, pass it through the designated initializer. This preserves all SectionKit data-source features while using standard UIKit layout logic:
import SectionUI
class PlainFlowViewController: UIViewController {
private let flowLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 10
layout.minimumInteritemSpacing = 10
return layout
}()
private lazy var collectionView = SKCollectionView(
frame: .zero,
collectionViewLayout: flowLayout
)
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
// SKCManager still powers sections and cells
collectionView.manager.reload([makeCustomSection()])
}
}
Handling Pinning Conflicts
When using native flow-layout pinning (sectionHeadersPinToVisibleBounds), you must disable SectionKit's pin plugins. The Plugin+Pin.swift file (lines 27-31) contains a debug assertion that triggers if both mechanisms are active:
class PinnedHeaderViewController: UIViewController {
private let collectionView = SKCollectionView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
// Enable native UIKit pinning
collectionView.collectionViewFlowLayout?.sectionHeadersPinToVisibleBounds = true
// Explicitly disable SectionKit pin plugins to avoid assertionFailure
collectionView.set(pluginModes: [
.verticalAlignment([]),
// Do NOT include .pinHeader or .pinFooter
])
collectionView.manager.reload([makePinnedSection()])
}
}
If you inadvertently enable both, the debug build will crash with the message: "SKCSectionPinOptions is not compatible with UICollectionViewFlowLayout's pinning feature."
Architecture Deep Dive
Understanding the source files helps clarify why SectionKit works with any layout.
SKCollectionView.swift
Located at Sources/SectionUI/CollectionView/SectionCollectionView/SKCollectionView.swift, this class bridges SectionKit to UIKit. It owns an SKCManager instance that manages sections and cells independent of layout calculations. The file exposes two critical initialization paths:
- Default initializer: Creates
SKCollectionFlowLayout(lines 37-41) - Custom layout initializer: Accepts any
UICollectionViewLayout(lines 42-46)
Both paths register the manager's request publishers, ensuring section updates work regardless of layout type.
Plugin+Pin.swift Assertions
The file Sources/SectionUI/Sections/Plugin+Pin.swift implements sticky headers and footers through SectionKit's plugin system. Lines 27-31 contain a compatibility guard:
#if DEBUG
if let layout = sectionView.collectionViewLayout as? UICollectionViewFlowLayout,
layout.sectionHeadersPinToVisibleBounds == true ||
layout.sectionFootersPinToVisibleBounds == true {
assertionFailure("SKCSectionPinOptions is not compatible with UICollectionViewFlowLayout's pinning feature...")
}
#endif
This prevents undefined behavior when both SectionKit plugins and native UIKit pinning attempt to control header/footer positioning.
Summary
- SectionKit supports UICollectionViewFlowLayout through the
init(frame:collectionViewLayout:)initializer inSKCollectionView.swift. - SKCManager handles all data-source and section logic independently of layout calculations, ensuring full feature compatibility.
- Layout plugins like pinning require
SKCollectionFlowLayout; disable them when using nativeUICollectionViewFlowLayoutpinning to avoid debug assertions inPlugin+Pin.swift. - Example implementations in
Example/Layouts/TestCollectionViewFlowLayout.swiftdemonstrate production-ready custom flow layouts with SectionKit.
Frequently Asked Questions
Can I use SectionKit's pin plugins with UICollectionViewFlowLayout?
No, SectionKit's pin plugins are incompatible with native UICollectionViewFlowLayout pinning. You must choose one mechanism. If you enable sectionHeadersPinToVisibleBounds on your flow layout, do not include .pinHeader or .pinFooter in your pluginModes array.
What happens if I enable both native pinning and SectionKit pin plugins?
The framework triggers an assertionFailure in debug builds at Plugin+Pin.swift (lines 27-31). This guard prevents runtime conflicts where both systems attempt to calculate sticky header positions. Release builds will not crash, but layout behavior becomes undefined.
Do I lose SectionKit features when using a custom flow layout?
You retain all core features including section abstraction, cell reuse, and data-source management through SKCManager. You only lose access to layout-specific plugins that depend on SKCollectionFlowLayout, such as advanced decoration views or SectionKit's proprietary pinning system.
How do I initialize SKCollectionView with a custom layout?
Use the designated initializer that accepts a layout parameter: SKCollectionView(frame:collectionViewLayout:). This injects your custom UICollectionViewFlowLayout while still initializing the internal manager and delegate-forwarding system required for SectionKit functionality.
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 →