Core Data:User数据已保存但无法获取的问题求助
Core Data关联数据读取异常问题排查
问题概述
使用Core Data管理数据:UserList实体存储登录用户的identifier,与Users、UserLinks、UserAllowedSellRoles、UserAllowedBuyRoles为一对多关系。调用saveUsers方法保存数据后,SQLite数据库确认Users数据已写入,但通过getUsersInfo读取UserList关联数据时,仅sellRoles、userLinks、buyRoles有数据,Users数据为空。已验证实体关系配置正确,近期新增Users实体的id约束并更新了Core Data模型版本,怀疑问题与数据迁移相关。
相关代码
保存方法
static func saveUsers(_ id: String, userDetails: [JSON?],userLinks: [JSON?], userBuyRoles: [JSON?], userSellRoles: [JSON?],completion:@escaping ( Bool) -> ()) { let context = CoreDataStack.shared.persistentContainer.viewContext context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy let request = NSFetchRequest<NSFetchRequestResult>(entityName: "UserList") request.returnsObjectsAsFaults = false request.predicate = NSPredicate(format: "identifier == '\(id)'") do { var usersArray = [Users]() for obj in userDetails { let entityUsers = NSEntityDescription.entity(forEntityName: "Users", in: context) let usersObj = NSManagedObject(entity: entityUsers!, insertInto: context) as! Users usersObj.id = Int16(obj?["id"].intValue ?? 0) usersObj.firstName = obj?["first_name"].stringValue usersObj.lastName = obj?["last_name"].stringValue //other properties related to user usersArray.append(usersObj) } var userLinksArray = [UserLinks]() for objUserLinks in userLinks { let entityUserLinks = NSEntityDescription.entity(forEntityName: "UserLinks", in: context) let userLinksObj = NSManagedObject(entity: entityUserLinks!, insertInto: context) as! UserLinks userLinksObj.url = objUserLinks?["url"].stringValue //other properties related to user links userLinksArray.append(userLinksObj) } var userAllowedSellRolesArray = [UserAllowedSellRoles]() for objSellRoles in userSellRoles { let entityUsers = NSEntityDescription.entity(forEntityName: "UserAllowedSellRoles", in: context) let userAllowedSellRolesObj = NSManagedObject(entity: entityUsers!, insertInto: context) as! UserAllowedSellRoles //properties related to user sell roles userAllowedSellRolesArray.append(userAllowedSellRolesObj) } var userAllowedBuyRolesArray = [UserAllowedBuyRoles]() for objBuyRoles in userBuyRoles { let entityUserAllowedBuyRoles = NSEntityDescription.entity(forEntityName: "UserAllowedBuyRoles", in: context) let userAllowedBuyRolesObj = NSManagedObject(entity: entityUserAllowedBuyRoles!, insertInto: context) as! UserAllowedBuyRoles //properties related to buy roles } let results = try context.fetch(request) as? [NSManagedObject] if results?.count ?? 0 > 0 { let userListObj = results?.first as! UserList userListObj.identifier = id userListObj.user = NSSet(array: usersArray) userListObj.userLinks = NSSet(array:userLinksArray) userListObj.buyRoles = NSSet(array:userAllowedBuyRolesArray) userListObj.sellRoles = NSSet(array:userAllowedSellRolesArray) try context.save() print("Stored Data Successfully") completion(true) }else { let entity = NSEntityDescription.entity(forEntityName: "UserList", in: context) let userListObj = NSManagedObject(entity: entity!, insertInto: context) as! UserList userListObj.identifier = id userListObj.user = NSSet(array: usersArray) userListObj.userLinks = NSSet(array:userLinksArray) userListObj.buyRoles = NSSet(array:userAllowedBuyRolesArray) userListObj.sellRoles = NSSet(array:userAllowedSellRolesArray) try context.save() print("Stored Data Successfully") completion(true) } } catch { print("Fetch Failed: \(error)") completion(false) } }
获取方法
static func getUsersInfo(_ completion:@escaping (NSArray,NSArray,NSArray ) -> ()) { let context = CoreDataStack.shared.persistentContainer.viewContext print("Fetching Data") let request = NSFetchRequest<NSFetchRequestResult>(entityName: "UserList") request.returnsObjectsAsFaults = false do { guard let results = try context.fetch(request) as? [NSManagedObject] else { return} for obj in results { let userObject = obj as? UserList let users = (userObject!.user! as NSSet).allObjects as NSArray let buyRoles = (userObject!.buyRoles! as NSSet).allObjects as NSArray let sellRoles = (userObject!.sellRoles! as NSSet).allObjects as NSArray print("users \(users)") print("buyRoles \(buyRoles)") print("sellRoles \(sellRoles)") completion(users,buyRoles,sellRoles) } } catch { print("Fetch Failed: \(error)") } }
排查方向与解决方案
1. 模型迁移导致关系映射失效
新增Users.id约束并更新模型版本时,可能破坏了UserList与Users的关联映射。
- 检查模型版本中
UserList与Users的关系配置:确认反向关系(Inverse)已正确设置,删除规则(Delete Rule)符合业务逻辑。 - 若使用手动迁移,重新生成迁移映射文件;若使用自动迁移,清理App缓存后重新测试,避免旧模型数据干扰。
2. 重复Users对象被合并导致关联丢失
由于新增了Users.id唯一约束,创建重复id的Users对象时,Core Data的合并策略可能丢弃新对象,但未正确维护UserList的关联关系。
- 修改
saveUsers中创建Users对象的逻辑,先查询是否已存在相同id的对象:for obj in userDetails { let userId = obj?["id"].intValue ?? 0 let userRequest = NSFetchRequest<Users>(entityName: "Users") userRequest.predicate = NSPredicate(format: "id == %d", userId) if let existingUser = try? context.fetch(userRequest).first { usersArray.append(existingUser) } else { let usersObj = Users(context: context) usersObj.id = Int16(userId) usersObj.firstName = obj?["first_name"].stringValue usersObj.lastName = obj?["last_name"].stringValue // 其他属性赋值 usersArray.append(usersObj) } } - 确保
Users实体已配置指向UserList的反向关系,Core Data依赖双向关系维护关联完整性。
3. 延迟加载导致读取时数据未加载
Core Data的延迟加载(Faulting)机制可能导致user关联数据未被实际加载,打印时仅显示Fault对象。
- 在
getUsersInfo的查询请求中添加预加载配置:request.relationshipKeyPathsForPrefetching = ["user", "buyRoles", "sellRoles"] - 或在读取时强制触发数据加载:
let users = (userObject!.user! as NSSet).allObjects as [Users] users.forEach { _ = $0.firstName } // 访问任意属性触发加载 completion(users as NSArray, buyRoles, sellRoles)
4. 合并策略覆盖原有关联
当前设置的NSMergeByPropertyObjectTrumpMergePolicy在更新UserList时,可能直接覆盖原有user关联,导致旧数据丢失。
- 更新已有
UserList对象时,合并新数据与原有关联,而非直接替换:if results?.count ?? 0 > 0 { let userListObj = results?.first as! UserList userListObj.identifier = id // 合并新Users数组与原有关联 let existingUsers = userListObj.user?.mutableCopy() as! NSMutableSet existingUsers.addObjects(from: usersArray) userListObj.user = existingUsers.copy() as? NSSet // 其他关联设置 userListObj.userLinks = NSSet(array:userLinksArray) userListObj.buyRoles = NSSet(array:userAllowedBuyRolesArray) userListObj.sellRoles = NSSet(array:userAllowedSellRolesArray) try context.save() completion(true) }
内容的提问来源于stack exchange,提问作者bumblebee
相关产品推荐
相关产品推荐

