iOS拉取解析JSON存Core Data出现重复记录如何解决?
Core Data 重复存储JSON数据解决方案
重复记录的根本原因是每次拉取数据时直接新建Core Data实体,未校验相同uid的已存在数据,且Core Data默认未开启唯一约束,以下是对应问题的标准实现方案:
1. 强制数据唯一性设置
Core Data的唯一约束通过数据模型配置实现,无需代码注解,操作步骤如下:
- 打开项目中的
.xcdatamodeld数据模型文件,选中TopEntity - 在Xcode右侧「数据模型检查器」(第三个标签,图标为尺子样式)找到「Constraints」配置栏
- 点击下方+号新增约束,输入属性名
uid并保存,即可将uid设为唯一主键 - 在
PersistenceController中配置上下文合并策略,避免唯一约束冲突时抛出错误:
init(inMemory: Bool = false) { container = NSPersistentContainer(name: "你的数据模型名称") // 配置合并策略:属性冲突时新数据覆盖旧数据 container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy if inMemory { container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") } container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) container.viewContext.automaticallyMergesChangesFromParent = true }
2. JSON列表数据合并方案
无需手动实现类似Android DiffUtil的差分逻辑,优化存储逻辑+系统内置的监听能力即可完成自动更新:
存储逻辑优化
避免循环中逐个查询数据库,采用批量查询+映射的方式提升性能,修改后的receiveValue代码如下:
.receiveValue: { [weak self] (returnedTops) in let context = PersistenceController.shared.container.viewContext // 收集所有返回数据的uid let uidList = returnedTops.data.map { Int32($0.id) } // 批量查询已存在的同uid实体 let fetchRequest: NSFetchRequest<TopEntity> = TopEntity.fetchRequest() fetchRequest.predicate = NSPredicate(format: "uid IN %@", uidList) guard let existingEntities = try? context.fetch(fetchRequest) else { return } // 建立uid到实体的快速映射 let existMap = Dictionary(existingEntities.map { ($0.uid, $0) }, uniquingKeysWith: { first, _ in first }) for top in returnedTops.data { let uid = Int32(top.id) let targetEntity: TopEntity if let existEntity = existMap[uid] { targetEntity = existEntity // 已存在则走更新逻辑 } else { targetEntity = TopEntity(context: context) // 不存在则新建 targetEntity.uid = uid } // 统一更新所有属性 targetEntity.elo = Int32(top.elo) targetEntity.given = top.given targetEntity.motto = top.motto targetEntity.photo = top.photo targetEntity.avg_score = top.avg_score ?? 0.0 targetEntity.avg_time = top.avg_time } self?.save() }
列表自动更新
SwiftUI中使用@FetchRequest查询TopEntity数据时,系统会自动监听Core Data的变化,数据更新后List会自动刷新UI,无需手动做差分计算。
内容的提问来源于stack exchange,提问作者Alexander Farber
相关产品推荐
相关产品推荐

