核心数据一对多关系在获取新对象后失去关系[重复]
Posted
技术标签:
【中文标题】核心数据一对多关系在获取新对象后失去关系[重复]【英文标题】:Core-data one to many relationship loses his relationship after fetching new objects [duplicate] 【发布时间】:2013-10-24 09:57:00 【问题描述】:我已经问过这个问题before。但我正在打开一个新的,因为我现在有一些其他的见解。首先这是我的core data model
的样子。
现在,当我将我的第一个 appointments
提取到我的模型中时。一切正常。但是当我加载新约会时问题就来了。然后之前的约会位置关系转到NULL
。奇怪的是location relationship
仅适用于最后加载的约会。
我使用restkit
将我的JSON
映射到我的core-data model
。这就是我建立这种关系的方式。
[locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"appointments" toKeyPath:@"appointments" withMapping:appointmentMapping]];
谁能帮我解决这个问题?
【问题讨论】:
只是一个建议,但是通过 SQLite 调试真的很痛苦。您可能会发现 PonyDebugger 很有用。 只是一个建议,但是原始的 JSON 反序列化器和直接的核心数据方法真的很简单,所以为什么不尝试不使用 RestKit 呢? 因为我需要将从 JSON 返回的对象保存到核心数据中,而我认为 restkit 做得很好。 您为其他问题添加了赏金 - 这是正确的做法,您应该为该问题添加新信息。 【参考方案1】:首先,您的模型很糟糕(无意冒犯)。您应该创建 LabelData、Data 和 VerplichtData 实体。这些应该与位置/约会具有一对一的关系。 Location 和 Appointment 应该与 LabelData、Data 和 VerplichtData 有一对多的关系。
您可能应该遵循 Mundis 的建议,而不是使用 rest kit,它可能会使调试更容易。 Apple has a pretty decent strategy for importing data in a smart way(即快速且无重复)。这里是来自文档的复制粘贴,以防链接失效:
高效地实现查找或创建 导入数据时的一种常见技术是遵循“查找或创建”模式,您可以设置一些数据来创建托管对象,确定托管对象是否已经存在,如果不存在则创建它。 在许多情况下,您可能需要为一组离散输入值查找现有对象(已保存在商店中的对象)。一个简单的解决方案是创建一个循环,然后对每个值依次执行一次 fetch 以确定是否存在匹配的持久化对象等。这种模式不能很好地扩展。如果您使用此模式分析您的应用程序,您通常会发现 fetch 是循环中更昂贵的操作之一(与仅迭代项目集合相比)。更糟糕的是,这种模式将 O(n) 问题变成了 O(n^2) 问题。 在可能的情况下,一次创建所有托管对象,然后在第二次处理中修复任何关系会更有效。例如,如果您导入的数据您知道不包含任何重复项(比如因为您的初始数据集为空),您可以只创建托管对象来表示您的数据,而根本不进行任何搜索。或者,如果您导入没有关系的“平面”数据,您可以为整个集合创建托管对象,并在使用单个大型 IN 谓词保存之前清除(删除)任何重复项。 如果您确实需要遵循查找或创建模式(例如,因为您要导入异构数据,其中关系信息与属性信息混合在一起),您可以通过将获取的次数减少到最少来优化查找现有对象的方式执行。如何实现这一点取决于您必须使用的参考数据量。如果您要导入 100 个潜在的新对象,而您的数据库中只有 2000 个,那么获取所有现有对象并缓存它们可能不会造成重大损失(特别是如果您必须多次执行该操作)。但是,如果您的数据库中有 100,000 个项目,那么保持这些缓存的内存压力可能会令人望而却步。 您可以结合使用 IN 谓词和排序来将 Core Data 的使用减少到单个 fetch 请求。例如,假设您想要获取一个员工 ID 列表(作为字符串)并为所有尚未在数据库中的人创建员工记录。考虑这段代码,其中 Employee 是一个具有 name 属性的实体,listOfIDsAsString 是您想要为其添加对象的 ID 列表(如果它们在商店中尚不存在)。 首先,对感兴趣的 ID(字符串)进行分离和排序。
// get the names to parse in sorted order
NSArray *employeeIDs = [[listOfIDsAsString componentsSeparatedByString:@"\n"]
sortedArrayUsingSelector: @selector(compare:)];
Next, create a predicate using IN with the array of name strings, and a sort descriptor which ensures the results are returned with the same sorting as the array of name strings. (The IN is equivalent to an SQL IN operation, where the left-hand side must appear in the collection specified by the right-hand side.)
// Create the fetch request to get all Employees matching the IDs.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:
[NSEntityDescription entityForName:@"Employee" inManagedObjectContext:aMOC]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:@"(employeeID IN %@)", employeeIDs]];
// make sure the results are sorted as well
[fetchRequest setSortDescriptors:
@[[[NSSortDescriptor alloc] initWithKey: @"employeeID" ascending:YES]]];
Finally, execute the fetch.
NSError *error;
NSArray *employeesMatchingNames = [aMOC executeFetchRequest:fetchRequest error:&error];
You end up with two sorted arrays—one with the employee IDs passed into the fetch request, and one with the managed objects that matched them. To process them, you walk the sorted lists following these steps:
Get the next ID and Employee. If the ID doesn't match the Employee ID, create a new Employee for that ID.
Get the next Employee: if the IDs match, move to the next ID and Employee.
Regardless of how many IDs you pass in, you only execute a single fetch, and the rest is just walking the result set.
下面的清单显示了上一节中示例的完整代码。
// Get the names to parse in sorted order.
NSArray *employeeIDs = [[listOfIDsAsString componentsSeparatedByString:@"\n"]
sortedArrayUsingSelector: @selector(compare:)];
// create the fetch request to get all Employees matching the IDs
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:
[NSEntityDescription entityForName:@"Employee" inManagedObjectContext:aMOC]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: @"(employeeID IN %@)", employeeIDs]];
// Make sure the results are sorted as well.
[fetchRequest setSortDescriptors:
@[ [[NSSortDescriptor alloc] initWithKey: @"employeeID" ascending:YES] ]];
// Execute the fetch.
NSError *error;
NSArray *employeesMatchingNames = [aMOC executeFetchRequest:fetchRequest error:&error];
【讨论】:
以上是关于核心数据一对多关系在获取新对象后失去关系[重复]的主要内容,如果未能解决你的问题,请参考以下文章
在插入新的子对象时,父子对象传递与多级的一对多关系。 IOS核心数据