使用UITableViewDiffableDataSource加载Maps分类时因标识符不唯一崩溃求助
Hey there, let's break down why your app is crashing when tapping the "Maps" category and how to fix it.
The Root Cause
The error *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Fatal: supplied identifiers are not unique.' tells us exactly what's wrong: UITableViewDiffableDataSource can't distinguish between some items in your Maps category.
Since you're using auto-synthesized Hashable conformance for your Item struct, the system generates a hash based on the combination of name, type, and text. If multiple items in the Maps category have identical values for all three properties (or even nil values that create duplicate hash combinations), the data source sees them as identical entries—even though they're separate in your JSON. This breaks the diffing logic that relies on unique identifiers to animate table view changes.
Step-by-Step Solutions
1. Add a Guaranteed Unique Identifier to Your Item Struct
The most reliable fix is to give each Item a truly unique identifier. You have two solid options here:
Option A: Use a Unique Field from the API
First, check the JSON response from the items API. Many APIs include a unique id field for each entry—if yours does, update your Item struct to include it:
struct Item: Codable, Hashable { var id: String // Match the actual unique field name from the API response var name: String? var type: String? var text: String? }
The auto-synthesized Hashable and Equatable implementations will now use this unique id to tell items apart, eliminating duplicate identifiers.
Option B: Generate a Local Unique ID
If the API doesn't provide a unique field, add a UUID property to Item that's generated when the struct is initialized:
struct Item: Codable, Hashable { var name: String? var type: String? var text: String? private(set) var uuid: UUID = UUID() // Manually implement Hashable to prioritize the unique UUID func hash(into hasher: inout Hasher) { hasher.combine(uuid) } // Manually implement Equatable to compare UUIDs static func == (lhs: Item, rhs: Item) -> Bool { return lhs.uuid == rhs.uuid } }
This ensures every Item gets a one-of-a-kind identifier, even if their other properties are identical.
2. Verify Duplicate Entries in Maps Data
To confirm this is the issue, add a quick debug check when loading the Maps category. Print out all items to see if any have identical name, type, and text:
// When parsing the Maps category entries for item in mapsCategory.entries { print("Name: \(item.name ?? "nil"), Type: \(item.type ?? "nil"), Text: \(item.text ?? "nil")") }
You'll likely see duplicate lines here, which confirms why the diffable data source is throwing an error.
Why Other Categories Work
It's just coincidence that your other 13 categories don't have duplicate item property combinations. The Maps category happens to have entries that look identical to the auto-synthesized Hashable logic, triggering the crash.
内容的提问来源于stack exchange,提问作者Laurent

