SwiftGridView has finally reached 1.0. I first released it back in 2016 as a way to learn Swift and publish a CocoaPod, and it has been sitting at 0.7.x for a while now. Enough had drifted out of date that a version bump was not going to cut it, so this release is a full modernization. It is also a breaking one.

Swift 6 and Strict Concurrency
The package now builds in Swift 6 language mode with complete strict concurrency checking, and the deployment target has moved to iOS 15. The manifest had been claiming iOS 10 while the podspec said iOS 12, so this also collapses three conflicting answers into one.
The migration turned out to be far less painful than expected. The library has no background work in it at all, and UICollectionView is already main-actor isolated by the SDK, so most of the work was making that isolation explicit with @MainActor rather than untangling actual data races.
A Pure Swift API
The datasource and delegate protocols were @objc protocols using @objc optional methods. That is what made the optional methods possible, but it also capped what the API could ever express: no value types, no generics, no Sendable. For 1.0 they are plain Swift protocols, and the optional methods have become default implementations in protocol extensions.
The interesting part was deciding what those defaults should do, because the methods fall into two very different groups. The ones returning values, like header heights or frozen column counts, default to zero, which the call sites already treat as “feature off” — so that behavior is preserved exactly. The ones returning views are different. They are only ever called once you have enabled the corresponding feature, and there is no sensible view to invent as a default. Returning an empty SwiftGridReusableView would bypass the reuse queue and silently render blank headers, which is worse than the old behavior of trapping loudly. So those defaults call fatalError with a message naming the method and the feature that requires it, which keeps the failure exactly as loud as before and considerably more explanatory.
SwiftUI Support
There is now a SwiftGrid view in the library. Previously the SwiftUI demo hand-rolled its own UIViewRepresentable, which meant every SwiftUI adopter had to write the same wrapper. It is now part of the package:
SwiftGrid(dataSource: model, delegate: model) { grid in
grid.register(MyCell.self, forCellWithReuseIdentifier: MyCell.reuseIdentifier())
}
The grid remains datasource and delegate driven, so the same objects work in both UIKit and SwiftUI. The wrapper holds onto them for you, since the underlying view references them weakly.
Swift Package Manager Only
CocoaPods support is gone, along with the podspec, the Podfiles, the committed Pods directories, and the old Xcode project and workspace. Maintaining a parallel distribution channel was adding clutter for very little remaining benefit. Xcode opens Package.swift directly and the example apps reference the package by local path.
Tests and CI
The old test target could not actually run — it mixed unit tests with a XCUITest stub that needed a host app, which does not work under SPM. It has been rebuilt with Swift Testing and now runs headless on the simulator on every pull request, covering layout math, frozen row and column pinning, grouped header spans, selection, and the SwiftUI wrapper. Formatting is enforced with swift-format, pinned to an exact version in a separate tools manifest so that consumers never have to resolve it as a dependency.
Documentation has moved from jazzy to DocC and is built and published by CI instead of being generated by hand and committed. One consequence worth calling out: the old documentation URLs no longer resolve.
Migrating from 0.7.x
Three things to be aware of:
- Remove
@objcfrom your conformances, and delete any optional methods you only implemented to satisfy the compiler. - Assign
dataSourceanddelegatein code. They can no longer be Interface Builder outlets, and a leftover storyboard connection will raiseNSUnknownKeyExceptionat load. This one caught my own example project. - Objective-C is no longer supported.
Conclusion
Ten years is a long time to leave something at 0.x. The API is smaller and more honest now, it is covered by tests that actually run, and the pieces that used to be manual are automated. The 1.0.0 release is on GitHub, and as always the source and examples are there as well.