2

我以前问过这个问题。但我正在打开一个新的,因为我现在有一些其他的见解。首先这是我的core data model样子。

在此处输入图像描述

现在,当我将我的第一个appointments放入我的模型中时。一切正常。但是当我加载新约会时问题就来了。然后之前的约会位置关系转到NULL。奇怪的是,location relationship唯一适用于最后加载的约会。

在此处输入图像描述

restkit用于将 my 映射JSON到我的core-data model. 这就是我建立这种关系的方式。

 [locationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"appointments" toKeyPath:@"appointments" withMapping:appointmentMapping]];

有人可以帮我解决这个问题吗?

4

1 回答 1

1

首先,你的模型很糟糕(没有冒犯)。您应该创建 LabelData、Data 和 VerplichtData 实体。这些应该与位置/约会具有一对一的关系。Location 和 Appointment 应该与 LabelData、Data 和 VerplichtData 有一对多的关系。

您可能应该遵循 Mundis 的建议,而不是使用 rest kit,它可能会使调试更容易。Apple 有一个相当不错的以智能方式导入数据的策略(即快速且无重复)。这里是来自文档的复制粘贴,以防链接失效:

有效地实现查找或创建 导入数据时的一种常见技术是遵循“查找或创建”模式,您可以在其中设置一些数据来创建托管对象,确定托管对象是否已经存在,并创建如果没有。在许多情况下,您可能需要为一组离散输入值查找现有对象(已保存在商店中的对象)。一个简单的解决方案是创建一个循环,然后对每个值依次执行一次 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];
于 2013-10-24T11:38:00.570 回答