DiffableDataSources: Apple's diffable data source, backported to older systems
💾 A library for backporting UITableView/UICollectionViewDiffableDataSource.
At a glance
- What is it?
- ra1028's DiffableDataSources reproduces the UITableView and UICollectionView diffable data source API on iOS 9, macOS 10.11 and tvOS 9 using the DifferenceKit diffing engine, at the cost of a different set of class names and a codebase whose last tagged release was 0.5.0 in 2021.
- Who is it for?
- DiffableDataSources is the right choice for an app that must support iOS 9, macOS 10.11 or tvOS 9 while still using a snapshot based data source model, and it is unnecessary for any project that can require iOS 13 or later, where Apple's own API is available.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 122 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why a backport exists when the official API ships with iOS 13
Apple announced a diffable data source at WWDC 2019. The README gives the motivation for this library in plain terms: the API makes updating table view and collection view items easy through automatic diffing, but it was a while before it could be used in a production service, because it requires the latest OS to use. DiffableDataSources makes it possible to introduce almost the same functionality in the meantime.
The problem the API solves is specific. In the older data source model, a table view or collection view holds a mutable array of items and a parallel array of section identifiers, and every mutation has to keep those arrays, the view, and your model in agreement. Get the order wrong and you get a crash or a stale cell. The diffable approach separates the data from the view: you build a snapshot describing sections and items, and the library works out the minimal set of insertions, deletions and moves needed to move the view from the old snapshot to the new one.
The diffing engine is not written here. The README states that the library uses a sophisticated open source library, DifferenceKit, by the same author, for the algorithm engine, and claims it avoids synchronization bugs, exceptions and crashes. That claim belongs to the project's own documentation rather than to an independent measurement.
The target audience is app teams with an older deployment floor that still want the snapshot model.
Different class names, same shape, and one behavioural difference
The backported types are deliberately renamed so they cannot collide with the official API if you later raise your deployment target. The README calls this difference in naming and provides a correspondence table.
NSDiffableDataSourceSnapshot maps to DiffableDataSourceSnapshot, UITableViewDiffableDataSource maps to TableViewDiffableDataSource, UICollectionViewDiffableDataSource maps to CollectionViewDiffableDataSource, and NSCollectionViewDiffableDataSource maps to CocoaCollectionViewDiffableDataSource.
The specification differences are listed too. The backport supports iOS 9.0+, macOS 10.11+ and tvOS 9.0+, uses an open sourced algorithm, allows duplicate sections or items, and performs diffing updates through performBatchUpdates.
Duplicate sections and items are the one that changes behaviour rather than naming. Apple's own implementation is stricter, and code written against the official API can rely on uniqueness. Code moved to this library may behave differently if it assumed uniqueness without checking.
Using performBatchUpdates also means the visual result is delivered by UIKit's batch update mechanism, which carries the usual constraints around reordering during an update.
Snapshots are applied, not mutated in place
The usage model has two halves. You define your section type conforming to Hashable, and an item type conforming to Hashable. An enum is suggested for sections because an enum conforms to Hashable by default, and it makes identification of sections across snapshots straightforward.
enum Section {
case main
}struct User: Hashable {
var name: String
}Then you create a data source, which attaches itself to the table view automatically, and dequeue cells through a closure:
final class UsersViewController: UIViewController {
let tableView: UITableView = ...
lazy var dataSource = TableViewDiffableDataSource<Section, User>(tableView: tableView) { tableView, indexPath, user in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = user.name
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
}The README describes the data source as intermediating DiffableDataSourceSnapshot, and makes the timing rule explicit: the UI is not updated until you apply the edited snapshot object, and the diffing animation is calculated automatically when you apply it.
let snapshot = DiffableDataSourceSnapshot<Section, User>()
snapshot.appendSections([.main])
snapshot.appendItems(users)
dataSource.apply(snapshot) {
// completion
}So the workflow is: build a snapshot, apply it, and let the library compute the transition.
Three installation paths and a Makefile for the library itself
The package is distributed through all three mainstream dependency managers, and the README gives the exact snippet for each.
CocoaPods, in the Podfile:
pod 'DiffableDataSources'Carthage, in the Cartfile:
github "ra1028/DiffableDataSources"Swift Package Manager, in the dependencies of Package.swift:
.package(url: "https://github.com/ra1028/DiffableDataSources.git", from: "x.x.x")The SwiftPM line is a template with a placeholder version, so you supply the version you want.
Working on the library itself is a separate path. The build instructions are:
$ git clone https://github.com/ra1028/DiffableDataSources.git
$ cd DiffableDataSources/
$ make setup
$ open DiffableDataSources.xcworkspaceThe Makefile shows what setup does, and the other targets tell you how the project is maintained:
setup:
git submodule update --init --recursive
gems-install:
bundle install --path vendor/bundle
docs-gen:
bundle exec jazzy --config .jazzy.ymlThe docs are generated with jazzy from a .jazzy.yml configuration, linting of the podspec runs through pod lib lint, and publishing goes through pod trunk push. That is a conventional iOS library toolchain, and the presence of a Gemfile and an azure-pipelines.yml means the build runs on Azure Pipelines rather than GitHub Actions.
Where the backport stops being the right answer
The first limit is the deployment floor. If your app can require iOS 13 or later, Apple's own diffable data source is available, is maintained by Apple, and needs no third party dependency. Taking a backport to that point is pure cost.
The second is the Swift and platform spread. The requirements are Swift 5.0+, iOS 9.0+, macOS 10.11+ and tvOS 9.0+, and the project carries a .swift-version file and a .swiftlint.yml. The library is Apple platform only, so there is no path for a server side or cross platform rendering of the same list logic.
The third is the release history. The tagged releases are 0.5.0 on 2021-06-08, 0.4.0 on 2020-04-12 and 0.3.0 on 2019-12-10. The last push was on 2026-06-23, so commits continue to land on master, but the published versions have not moved in five years. Adopting a 0.x library that is still receiving commits but has not cut a release since 2021 means you will likely be consuming a commit or a fork rather than a tagged artefact.
The fourth is the duplicate tolerance. Allowing duplicate sections and items removes a check that would catch a genuine bug in your own model.
The fifth is the dependency chain: your app then depends on this library and on DifferenceKit, and the class names differ from Apple's, so a future migration is a rename plus a delete rather than a delete.
Licence, examples and the maintenance picture
The project is published under the Apache-2.0 licence, with the LICENSE file at the repository root and a licence badge in the README. Apache-2.0 is permissive and includes an explicit patent grant, and it is a licence many teams prefer for a dependency because it carries those terms rather than only a copyright grant. Read the file for the obligations that attach to redistribution.
The examples directory holds an iOS example, a macOS example, a MountainsRawData.swift file and its own README, with example projects set up as a workspace. The README points to API documentation hosted at ra1028.github.io/DiffableDataSources, to the example apps, and to the WWDC 2019 session that introduced the original API, which is the best source for the design intent behind the snapshot model.
The default branch is master rather than main, which matters if you script against this repository. The top level also carries Cartfile and Cartfile.resolved, a Package.swift and Package.resolved, a podspec, a Gemfile, XCConfigs, a jazzy configuration and CODE_OF_CONDUCT.md, so the repository holds every piece of the release pipeline for three package managers.
Contributions go through pull requests, and the contributing guidance is linked from the README. The build badge points at Azure Pipelines, which is where the test suite for this project runs.
Editorial conclusion
DiffableDataSources is the right choice for an app that must support iOS 9, macOS 10.11 or tvOS 9 while still using a snapshot based data source model, and it is unnecessary for any project that can require iOS 13 or later, where Apple's own API is available. Before adopting it, read the naming table and plan for the class name differences, check that the DifferenceKit dependency resolves for your Swift version, and pin the version, since the last tagged release is 0.5.0 from 2021-06-08 even though the last push was on 2026-06-23.
Frequently asked questions
What is DiffableDataSources and which platforms does it support?
It is a library that backports Apple's UITableView and UICollectionView diffable data source to older systems, powering the diffing with the DifferenceKit library. The README lists support for iOS 9.0+, macOS 10.11+ and tvOS 9.0+, with Swift 5.0+ required.
How do I install DiffableDataSources with Swift Package Manager?
Add the package to the dependencies of your Package.swift. The README gives the template .package(url: "https://github.com/ra1028/DiffableDataSources.git", from: "x.x.x"), where you replace the placeholder with the version you want. CocoaPods and Carthage snippets are also documented.
How do I apply data to a DiffableDataSources table view?
Create a DiffableDataSourceSnapshot, append sections and items to it, then call apply on the data source with the snapshot. The README states that the UI is not updated until the edited snapshot is applied, and the diffing animation is calculated automatically at that point.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ra1028-diffabledatasources)Was this useful?