A small iOS sample app demonstrating UICollectionViewDiffableDataSource with a compositional layout and a simple MVVM flow. It fetches adoptable animals from the Petfinder API and shows main / loading / error states using distinct collection view sections.
- UICollectionView with UICollectionViewCompositionalLayout
- UICollectionViewDiffableDataSource to manage items and sections
- MVVM-style AnimalsViewModel that handles paging and load-more
- Dedicated cells for animals, loading shimmer, and error + retry
- Pull-to-refresh and infinite scroll (load more when last cell appears)
- Simple image loading for animal photos
- Language: Swift
- Platform: iOS (Xcode project included)
- Notable APIs / patterns: UICollectionViewDiffableDataSource, UICollectionViewCompositionalLayout, async/await networking
How it fits together:
- ViewController owns the collection view and the diffable data source. It asks AnimalsViewModel to fetch data and reacts to callbacks to update snapshots.
- AnimalsViewModel performs network calls through NetworkService and exposes simple closures for UI updates (onFetchStarted, onAnimalsUpdated, onError, onLoadMoreStarted).
- NetworkService decodes Petfinder responses into local
Animalmodels used by the UI.
- Clone the repo:
git clone https://github.com/mauricetinn/diffable-data-source-sample.git cd diffable-data-source-sample
- Open the Xcode project:
- Double-click
diffableDataSourceSample.xcodeprojor run:open diffableDataSourceSample/diffableDataSourceSample.xcodeproj
- Configure the Petfinder API token (see Security note below).
- Select a Simulator or device and run (Cmd+R).
There are no external dependencies or package managers required — just Xcode.
This project currently contains a hardcoded access token inside NetworkService.swift. Replace this with a safe configuration before shipping or publishing the repo.
Recommended approaches:
- Use environment variables in the Xcode run scheme:
- Edit Scheme → Run → Arguments → Environment Variables → add
PETFINDER_TOKEN=your_token - Then in NetworkService, read the token at runtime:
private let accessToken = ProcessInfo.processInfo.environment["PETFINDER_TOKEN"] ?? ""- Or store a key in
Info.plist(less secure) and read it withBundle.main.infoDictionary?["PETFINDER_TOKEN"] as? String.
You must obtain a Petfinder access token from https://www.petfinder.com/developers/ and set it before running requests.
- Add cell selection handling (tap to show detail).
- Extract image loading to a dedicated caching image loader (e.g., use URLCache or a library).
- Make sections more flexible (separate section types and supplementary views).
- Improve error handling and show more descriptive UI for different failure types.
- Replace hardcoded token with secure storage / secrets manager.
Note: There is a TODO comment in ViewController.swift listing items such as delegate handling, dynamic cell heights, more sections, handling of negative cases, loading state and tap actions.
A token-like string is present in NetworkService.swift. Treat it as sensitive — rotate it now if that credential is real, and remove it from the repository history. Use environment variables or other secure configuration methods instead of committing secrets.
- Open an issue or submit a PR with improvements (image caching, decoupling network code, tests, etc.).
- Keep changes focused and add short descriptions for behavior changes.
No license file present. Add a LICENSE if you want to open-source this project.
- How can I add image caching to avoid re-downloading images when scrolling?
- Where should I put unit tests for AnimalsViewModel to mock the NetworkService?
- How can I adapt the compositional layout to support a detail view with a larger single-column section?