【问题标题】:NSPredicate not executedNSPredicate 未执行
【发布时间】:2012-06-28 02:06:28
【问题描述】:

这很有趣。 在我的应用程序中,我在数据库中创建了数千个条目(在另一个线程中,我使用的是 MagicalRecord)。一切似乎都运行良好(从背景/前景/上下文的角度来看)。

当我在主线程中尝试获取“刚刚插入”的数据时,我发现了以下行为:

- (NSArray *) familiesInCompany:(Company *) company {
  NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"company == %@", company];
  NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"company.name == %@", company.name];

  NSArray *first = [Family MR_findAllSortedBy:@"name" ascending:YES withPredicate:predicate1];
  NSArray *second = [Family MR_findAllSortedBy:@"name" ascending:YES withPredicate:predicate2];
  NSArray *third = [Family MR_findByAttribute:@"company" withValue:company andOrderBy:@"name" ascending:YES];

  return second;
}

现在我得到的是:

  • first:是一个空数组
  • second:包含所有 Family 对象,如预期的那样
  • 第三个:是一个空数组。

通过调试 SQL 语句,我得到以下信息:

“第一个”陈述:

CoreData:注释:总提取执行时间:0 行 0.0000 秒。

“第二个”声明:

CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZCOMPANY FROM ZFAMILY t0 JOIN ZCOMPANY t1 ON t0.ZCOMPANY = t1.Z_PK WHERE t1.ZNAME = ?按 t0.ZNAME 排序

CoreData:注解:sql连接获取时间:0.0005s

CoreData:注释:总提取执行时间:2 行 0.0007 秒。

“第三”陈述:

CoreData:注释:总提取执行时间:0 行 0.0000 秒。

有趣的是我关闭了应用程序(我的意思是真正手动终止它)然后我打开它,所有三个“获取”语句都起作用了。

为什么第一个和第三个 fetch 语句似乎永远不会被执行?如何深挖问题?

【问题讨论】:

  • 我认为基本相同的问题是 NSFetchedResultsController 实现。最近创建的记录没有显示在获取结果中,但是当我直接检查时已写入持久存储 - 正确的计数甚至显示在关系 NSSet 中,但 NSPredicate 没有看到它们。诡异的。使用 MagicalRecord 2 - 以前的项目使用 1.x 版本并且没有问题,所以我可能只是改变路线并使用旧版本。
  • 天真(有点离题)的问题:你是如何记录 sql 语句的?我真的很好奇如何在我的应用程序中执行此操作以更好地理解谓词
  • @FabianoFrancesconi 太棒了,谢谢!

标签: ios sqlite core-data nspredicate magicalrecord


【解决方案1】:

我遇到了同样的问题,这是我想出的,以及我是如何解决的。

Magical Record 有一个根 NSManagedObjectContext 作为默认 NSManagedObjectContext 的父级。当我在默认上下文中创建 NSFetchedResultsController 时,一切似乎都正常,就像你一样。

问题是所有 NSManagedObject 都带着他们仍然临时的ObjectID 回来了。因此,就我而言,我使用NSPredicate 来确定关联表上的查询范围。我不只是调用关联方法,因为我不想将 所有内容 加载到内存中,并且希望 NSFetchedResultsController 为我处理更改。

使用临时 ObjectID,查询会找到零个结果,而这正是它所显示的。

显然,子上下文(默认)没有从转换为非临时 ID 的好处,即使它已被持久化到后备存储。

当我试图用obtainPermanentIDsForObjects:error: 强制解决问题时,更糟糕的事情发生了。 Core Data 抱怨它无法满足我的实例的故障。没关系,这不可能实际上是一个错误。简单地刷新对象也没有效果。我怀疑这是一个核心数据错误,几乎没有人会发痒,因为他们只是使用关联方法来获取 NSSet。

我的解决方法是使用 NSFetchedResultsController 的父上下文,就像在这个问题中一样,Magical Record, saving, and NSFetchedResultsController

我已经在编辑时将默认值包装在一个新的子上下文中,因此,使用createInContext 将实例复制到该编辑上下文中,因此我不需要做任何额外的工作,只需将.parentContext 添加到论据。

顺便说一句,这只发生在关联源的新实例上。一旦实例从启动开始就存在,它有一个非临时的ObjectID 并且从未出现过问题。

【讨论】:

  • 对不起,我想我错过了一些东西。您的建议是使用“currentContext.parentContext”创建“资源”?
  • 不完全是,这就是我传递给 Magical Record fetch* 方法的内容。对象创建(和修改)发生在 MR_defaultContext 及其父级的子上下文中。
  • 示例代码,[Model fetchAllSortedBy:@"qqq" 升序:NO withPredicate:predicate groupBy:@"qqq" delegate:self inContext:self.managedObjectContext.parentContext];在这种情况下,self.managedObjectContext 与 MR_defaultContext 相同。
  • 我在使用内存中持久存储的测试期间遇到了类似的问题,并且在我删除所有上下文保存后问题就消失了。大概这意味着临时 ObjectID 仍然是正确的,并且保存后它不会在默认上下文中刷新也没关系。
  • 我认为这与合并上下文有关。也就是说:即使我在通过MR_contextThatPushesChangesToDefaultContext 创建的新上下文上调用 MR_saveNestedContexts 时,也永远不会调用 - (void) MR_mergeChangesOnMainThread:(NSNotification *)notification 方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-14
  • 2012-08-23
  • 2023-03-07
  • 1970-01-01
相关资源
最近更新 更多