Articles
Diffable Data Source Interview Questions: Item Identity, Snapshots, and Cell Updates
Practice diffable data source interview questions with stable-ID snapshots, duplicate-identifier traps, and a reconfigure-versus-reload decision.
A diffable data source can animate a list beautifully and still display the wrong item. The central interview question is not how to call apply; it is what an item identifier means across two snapshots. If the identifier changes with presentation text, an edit can look like a deletion and insertion. If two rows share an identifier, the snapshot cannot represent both. If the identifier stays stable but the cell's content changes, the app must tell the data source which visible cell needs an update.
Official Apple facts below come from UIKit's diffable data source and snapshot documentation. The Bookmarks inbox, trace table, and test cases are editorial exercises, not a measured app run or candidate report. No employer-specific interview process is claimed. The question is useful for any collection or table view where models change faster than cells can safely be managed by index path.
What is the identity contract?
Apple's diffable data source guide describes snapshots in terms of sections and unique item identifiers. The data source compares one snapshot with the next and applies the difference. An identifier should represent the same logical item before and after a move, title edit, or status update. It should be hashable and unique among items in a snapshot.
Take an editorial Bookmarks inbox with server records B17, B18, and B19. The first snapshot displays B17 with title “Review API,” B18 with “Read design,” and B19 with “Ship note.” The second snapshot reorders B18 to the top and changes the title of B17. A stable identifier is the record ID. The move is a move; the title change is a content change. A title-as-identifier design instead makes B17 appear to be a new item, so a title edit can produce an unnecessary delete/insert animation and lose selection or cell state.
This is not an argument that every backend ID is automatically safe. Define its namespace. If the feed combines two account databases that can both contain record 17, an identifier may need (accountID, recordID). If the backend reuses IDs after deletion, decide whether a later record is a new logical item. The interview answer should specify the equality rule, not merely say “use UUIDs.”
What breaks when equality or hashing includes mutable content?
Consider a Bookmark value that conforms to Hashable by synthesizing equality over id, title, and isRead, then is used directly as the snapshot item identifier. Editing title changes how that identifier compares with its old value. The data source may treat the updated value as another identity. In a reference type, mutating a field used by hashing after the object has entered hash-based state can make lookups inconsistent. Both failures stem from using changing presentation data to define identity.
A safer design passes a small, immutable BookmarkID into the diffable data source and keeps current presentation data in a separate model store keyed by that ID. The cell provider receives an ID, fetches the latest model, and configures the cell. An update changes the store and marks the affected ID for reconfiguration or reload in the next snapshot. The model store's update and snapshot application must be ordered so the cell does not read stale data.
What if two sections show the same bookmark, once in “Unread” and once in “Pinned”? Apple's snapshot documentation requires unique identifiers in a snapshot. If those are two presentations of the same record that must both be visible, use distinct presentation IDs such as (recordID, placement) and map both back to the record. If the product intends one row that moves sections, use the record ID once. The identity model follows the UX requirement.
How do you trace a snapshot update?
Make a compact transition ledger before touching UI code. For the Bookmarks inbox, suppose the initial order is [B17, B18, B19]. The server response says [B18, B17, B20]: B18 moved, B19 disappeared, B20 arrived, and B17 changed title. Construct the desired final snapshot from the response rather than applying a stream of index-path inserts and deletes to an assumed current index layout.
| Identifier | Before | After | Expected UI interpretation |
|---|---|---|---|
B18 | Position 2 | Position 1 | Same item moved. |
B17 | Position 1, old title | Position 2, new title | Same item moved and cell content updated. |
B19 | Position 3 | Absent | Item removed. |
B20 | Absent | Position 3 | Item inserted. |
This ledger is an editorial debugging artifact. It makes a common interview trap visible: applying the new snapshot can represent structural moves, inserts, and deletions, but it does not automatically inspect the app's model objects for changes to a cell's text. Apple's guide says the app is responsible for identifying data changes that need to be reflected in existing cells. Mark B17 explicitly.
When should a cell be reconfigured or reloaded?
Apple's reconfigureItems reference draws a useful boundary: reconfiguration updates the existing cell and is suitable when its type need not change; reloading can replace the cell when a different cell type is needed. For the B17 title or read badge, update the model store and reconfigure B17. If the item changes from a compact bookmark cell to a media-preview cell requiring a different registration or layout, reload may be the right choice.
Do not call these operations on an ID that is absent from the intended snapshot. First decide whether the item should exist. Then decide whether a retained item needs content refresh. Avoid a “reload everything” response: it hides the identity bug, does needless work, and can disrupt transient cell state. Conversely, do not assume a stable ID means a cell automatically rereads the model. Identity and content invalidation are separate responsibilities.
Suppose a custom cell owns an in-progress text edit or accessibility focus. A reconfigure operation that retains the cell may preserve more state, but the configuration code can still overwrite user input if it blindly resets every field. The candidate should name the cell's state owner and update only the fields whose model version changed. That is an engineering inference from the documented reuse semantics, not a promise that UIKit preserves every custom property.
How do asynchronous responses affect snapshot correctness?
Diffable data sources solve a UI-difference problem, not a request-order problem. Imagine search query ca is sent, then cat; the cat response arrives first and is applied, then the slower ca response arrives. A perfectly valid snapshot can still regress the screen to stale results. Attach a query generation or request token to each response and apply it only if it belongs to the current search state. If the product supports merging pages, use a versioned merge rule instead of simply discarding all older responses.
Paginated feeds add a second identity trap. Page 2 may repeat the boundary item from page 1. Appending IDs blindly creates a duplicate. Deduplicate by the stable logical ID and define whether the later copy supplies fresher content. Then build a snapshot whose section/item identifiers are unique. If the list supports optimistic “mark read,” reconcile server acknowledgement against the local version so a late page response does not reverse the optimistic change.
An interview answer can describe the pipeline as fetch → validate version → update model store → build unique snapshot → mark retained changed IDs → apply. The sequence is an editorial design pattern. It is not a claim that UIKit chooses or enforces your network consistency policy. Keeping this boundary explicit makes race analysis easier.
There is also a snapshot-ownership decision. If several features can write the same list, do not let each feature independently take an old snapshot, modify it, and apply it later without coordination. A favorites toggle and a page-load response can race: one snapshot may contain the new favorite badge while the other contains the new page, and the last apply can erase the first change. Instead, reconcile both events into one authoritative model state, then derive the next snapshot from that state. The data source can animate that state; it cannot decide which business event wins.
For debugging, record a monotonically increasing model version with the IDs and section order used to build each snapshot. If the UI appears to go backward, compare the version of the last applied snapshot with the current model store. This is an editorial instrumentation suggestion, not a UIKit API requirement. It turns an intermittent visual symptom into a concrete sequencing question and avoids blaming cell reuse when the real defect is stale input.
What should be tested rather than guessed?
Start with pure identity tests. Two presentations of the same record should compare equal only if the UI intends one row. Different records with the same title must compare unequal. A title or read-status edit must not change the item ID. A duplicate (recordID, placement) should be rejected or folded before snapshot creation. These tests catch model-contract defects without relying on animation timing.
Next test state transitions. Given the two snapshots in the ledger, assert the intended final order and the set of retained-but-changed IDs. Simulate two search responses arriving in reverse order and ensure the older generation cannot overwrite the newer state. Simulate a repeated page-boundary ID. In a UI test, check that selection, focus, or scroll behavior matches product expectations after a move and content refresh. A screenshot alone cannot prove the identifier contract.
If an actual app crashes or shows stale text, capture the incoming IDs, old snapshot, new snapshot, and model-store version. Ask whether the failure begins before apply (bad source data), during snapshot construction (duplicate or wrong identity), or after application (cell provider/configuration reads stale content). This separates three causes that often look like “diffable is flaky.”
Fast interview answers
Should the whole model be the item identifier? Only if its equality/hash semantics are stable and match logical identity. A small immutable ID plus a model store is usually clearer.
Can the same identifier occur in two sections? Not within one snapshot. If two visible placements are required, model distinct presentation identities.
Will apply notice that a title changed? Do not rely on it to inspect model content. Mark the retained item for reconfiguration or reload.
When is reload appropriate? When the update requires replacing the cell or changing its type/configuration in a way reconfiguration cannot serve.
Does diffing prevent stale search results? No. Gate asynchronous responses by the current query/version before building the snapshot.