NSPredicate未执行 [英] NSPredicate not executed

查看:165
本文介绍了NSPredicate未执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这很有趣。
在我的应用程序中,我在数据库中创建了数千个条目(在另一个线程中,我使用MagicalRecord)。一切似乎工作正常(从背景/前景/上下文的角度)。



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

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

NSArray * first = [Family MR_findAllSortedBy:@nameascending:YES withPredicate:predicate1];
NSArray * second = [Family MR_findAllSortedBy:@nameascending:YES withPredicate:predicate2];
NSArray * third = [Family MR_findByAttribute:@companywithValue:company andOrderBy:@nameascending:YES];

return second;
}



现在我得到的是:




  • 第一个是空数组

  • 第二个:包含所有 Family


$ b 通过调试SQL语句我会得到如下:



first语句:


CoreData:annotation:总获取执行时间:0行的0.0000s。


second语句:


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 =?ORDER BY t0.ZNAME



CoreData:注释:sql连接提取时间:0.0005s



CoreData:annotation:total fetch execution time:0.0007s for 2 rows。


third语句:


CoreData:注释:总获取执行时间:0行为0.0000s。


热闹的事情是,我关闭应用程序(我的意思是手动终止它),我打开它,所有三个提取语句工作。



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

解决方案

我有同样的问题,这是我想出来的, 。



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



问题是所有的 NSManagedObject -temporary ObjectID 的。所以,在我的情况下,我使用 NSPredicate 来限定关联表上的查询。我不是只调用关联方法,因为我不想加载所有到内存,并希望 NSFetchedResultsController 来处理更改。



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



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



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



我的修复是使用父上下文 NSFetchedResultsController ,就像这个问题一样,魔法记录,保存和NSFetchedResultsController



我已经在编辑时将默认包装在一个新的子上下文中,因此将实例复制到编辑上下文与 createInContext ,所以我不需要做任何额外的工作,只是添加 .parentContext 到参数。 / p>

顺便说一句,这只发生在关联的源的新实例上。一旦一个实例从启动开始,它有一个非临时 ObjectID ,从来没有遇到过这个问题。


This is quite funny. In my application I create thousands of entry in the database (in another thread, I'm using MagicalRecord). Everything seems working fine (from a background/foreground/context point of view).

When, in the main thread, I try to fetch the "just inserted" data, I discovered the following behaviour:

- (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;
}

Now what I get is:

  • first: is an empty array
  • second: contains all the Family objects, as expected
  • third: is an empty array.

By debugging the SQL statement I get the following:

The "first" statement:

CoreData: annotation: total fetch execution time: 0.0000s for 0 rows.

The "second" statement":

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 = ? ORDER BY t0.ZNAME

CoreData: annotation: sql connection fetch time: 0.0005s

CoreData: annotation: total fetch execution time: 0.0007s for 2 rows.

The "third" statement:

CoreData: annotation: total fetch execution time: 0.0000s for 0 rows.

The hilarious thing is that I close the application (I mean really manually terminate it) and and I open it back, all the three "fetching" statements work.

Why the first and the third fetch statements seem to never being executed? How to dig into the problem?

解决方案

I had this same issue, this is what I figured out, and how I resolved it.

Magical Record has a root NSManagedObjectContext as a parent of the default NSManagedObjectContext. When I create an NSFetchedResultsController in the default context, everything seems to work fine, just like you.

The problem is that all the new NSManagedObject's come back with their still-temporary ObjectID's. So, in my case, I was using an NSPredicate to scope a query on an associated table. I didn't just call the association method because I didn't want to load everything into memory and wanted NSFetchedResultsController to handle changes, for me.

With the temporary ObjectID the query finds zero results and that's exactly what it displays.

Apparently the child context (default) doesn't get the benefit of the transformation to non-temporary ID's, even though it's been persisted to the backing store.

Even worse badness happened when I tried to force the issue with obtainPermanentIDsForObjects:error:. Core Data complained that it could not satisfy a fault for my instance. Nevermind, there's no way it was actually a fault. Simply refreshing the object had no effect, either. I suspect this is a Core Data bug that hardly no one tickles because they just use the association methods to get an NSSet.

My fix was to use the parent context for the NSFetchedResultsController, just like in this question, Magical Record, saving, and NSFetchedResultsController.

I was already wrapping the default in a new child context upon edit and, therefore, copying the instances into that editing context with createInContext, so I didn't have to do any extra work beyond just adding .parentContext to the argument.

Incidentally, this only ever happened on new instances of the source of the association. Once an instance was there from startup, it had a non-temporary ObjectID and never had the issue.

这篇关于NSPredicate未执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆