核心数据获取谓词零检查失败/意外结果?

时间:2015-06-26 21:48:13

标签: ios core-data restkit nspredicate nsfetchrequest

我有一个包含数千个实体的核心数据层,不断与服务器同步。同步过程使用获取请求来检查deleted_at以进行软删除。在performBlockAndWait调用中有一个上下文执行保存操作。关系映射由RestKit库处理。

CoreDataEntity类是NSManagedObject的子类,它也是我们所有不同核心数据对象类的超类。它有一些由我们所有实体继承的属性,例如deleted_at,entity_id和所有样板提取和同步方法。

我的问题是一些获取请求似乎在修改对象后返回不一致的结果。例如,删除对象(将deleted_at设置为当前日期)后:

[CoreDataEntity fetchEntitiesWithPredicate:[NSPredicate predicateWithFormat:@"deleted_at==nil"]];

使用deleted_at == [今天的NSDate]

返回结果

我通过额外循环结果并删除了设置了deleted_at的实体,成功解决了这种问题,但是我无法解决相反的问题:

[CoreDataEntity fetchEntitiesWithPredicate:[NSPredicate predicateWithFormat:@"deleted_at!=nil"]];

在相同条件下返回一个空数组,阻止服务器同步成功。

我确认已在对象上设置了deleted_at,并且上下文保存成功。我只是不明白在哪里重置任何缓存导致过时的结果?

感谢您的帮助!

编辑:添加更多信息,似乎一旦这些对象中的一个被破坏,让它进行注册的唯一方法是再次修改该值。这可能是某种类型的核心数据索引在修改值时无法更新吗?

更新:RestKit https://github.com/RestKit/RestKit/issues/2218

似乎存在问题

3 个答案:

答案 0 :(得分:0)

首先,在保存之后,您在商店中查看以确保您的更改存在吗?如果没有看到整个Core Data堆栈,就很难深入了解可能出现的问题。如果您正在保存并且您在商店中看到更改,那么问题就会出现在您的上下文中。它们是如何构建的以及何时构建如果您正在处理可能导致您的问题的兄弟情境。

核心数据堆的外观需要更多细节。

  

是的,有变化。正如我在问题中提到的,我可以遍历我的结果并删除所有已成功设置deleted_at的内容

那不是我的问题。查看内存中的对象与在磁盘上的SQLite文件中查看它们之间存在差异。我对这种行为的疑问是:

  1. 在您再次查询更改之前,更改是否保留在磁盘上
  2. 您是否正在使用多个上下文并可能尝试从过时的兄弟中获取。
  3. 因此,我对磁盘更改以及核心数据堆栈的内容有所了解。

    线程

    如果您使用的是某个上下文,那么您的应用中是否使用了多个线程?如果是这样,您是否在多个线程上使用该上下文?

    我可以看到一种情况,如果你违反了线程限制规则,你可能会破坏这样的数据。

答案 1 :(得分:0)

你显然正在使用一些sintactic糖扩展到核心数据。我想在你的情况下它是一个SheepData,对吗?

fetchEntitiesWithPredicate:实施如下:

+ (NSArray*)fetchEntitiesWithPredicate:(NSPredicate*)aPredicate
{
    return [self fetchEntitiesWithPredicate:aPredicate inContext:[SheepDataManager sharedInstance].managedObjectContext];
}

您确定[SheepDataManager sharedInstance].managedObjectContext收到您对对象所做的所有更改吗?它是接收保存通知,还是保存上下文的子上下文?

尝试用以下方法替换你的fetch one-liner:

[<your saving context> performBlockAndWait:^{
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"CoreDataEntity"];
    request.predicate = [NSPredicate predicateWithFormat:@"deleted_at==nil"];

    NSArray *results = [<your saving context> executeFetchRequest:request error:NULL];
}];

答案 2 :(得分:-1)

尝试添加一个额外的属性deleted,这是一个默认为false的bool。然后始终设置该属性,您可以根据当前的需要查找truefalse的实体。如果值为true,那么您可以查看deleted_at以了解详情。

或者尝试将deleted_at属性设置为某个旧日期(可能是1980年1月1日),然后任何未删除的内容都会有一个太旧而无法由用户设置的固定日期。 / p>

编辑:deleted_at可能存在一些问题,从未涉及某些混淆系统的实体。您也可以将获取请求设置为以字典样式返回结果,在这种情况下,最近的更改不会反映在获取结果中。