NSFetchRequest不捕获具有已更改属性的对象

时间:2011-08-19 22:51:26

标签: sql macos cocoa core-data nsfetchrequest

我使用SQL存储在MacOsX 10.6上遇到了CoreData的奇怪问题。我有一个名为NSManagedObject的{​​{1}}子类,其属性为Family,关系name连接到名为personList的另一个NSManagedObject子类,其属性为{{1}和反向关系Personfirstname只有一个familyPerson可以有多个family

假设我有一个family对象Person指向家庭'Doe',其中2 Family(John和Jane)连接到它,我执行以下请求:

family

我得到一个2人的阵列:Jane和John,姓氏为Doe。现在,如果我使用其合成访问器更新系列,在我的情况下:

Person

我使用相同的获取请求获取NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; [request setEntity:[NSEntityDescription entityForName:@"Person" inManagedObjectContext:managedObjectContext]]; [request setPredicate:[NSPredicate predicateWithFormat:@"family.name=%@",[family name]]]; NSArray *array = [managedObjectContext executeFetchRequest:request error:&error]; 列表后无法获取。结果是[family setName:@"Wheat"] 的{​​{1}}。

如果我将谓词更改为以下行,它将再次起作用:

Person

所以就好像Predicate没有使用该系列属性名的更新版本,即使我将[array count]设置为默认值(因此0返回YES)。这对我来说毫无意义。似乎[request setPredicate:[NSPredicate predicateWithFormat:@"family=%@",family]]; 找到NSFetchRequest对象,但未能看到其值includesPendingChanges已更新,未保存,并且位于内存中的NSFetchRequest。当然,如果我保存商店,那么它又会再次运作。

有什么想法吗?我已经浏览了Mac文档,但看不出为什么会失败。

3 个答案:

答案 0 :(得分:4)

我认为这里的关键是理解获取请求。它从持久性存储中检索数据,因此很明显,如果您没有保存到持久性存储,它将无法找到该数据。如果你考虑到这一点,你描述的情况是完全合乎逻辑的。

来自核心数据编程指南:

  

您无法使用基于瞬态属性的谓词进行提取   (尽管您可以使用瞬态属性在内存中进行过滤   你自己)。此外,在提取和提取之间存在一些交互   商店的类型 - 有关详细信息,请参阅“商店类型和行为”   但总结一下,如果直接执行提取,应该   通常不会添加基于Objective-C的谓词或将描述符排序到   获取请求。相反,你应该将这些应用于结果   获取。如果使用数组控制器,则可能需要子类   NSArrayController所以你可以让它不传递排序描述符   持久存储,而不是在数据之后进行排序   被抓了。

答案 1 :(得分:2)

总而言之,我一直在仔细测试我的代码,这就是我如何看待CoreData关于Fetching和objective-c谓词的限制(即点符号)。

  

如果一个对象已被Objective-C程序访问,并且如果其属性或关系之一已被修改,则任何带有使用点表示法的谓词的NSFetchRequest将返回SQL存储的结构,因此结果将是错误的。

如果是琐碎的家庭示例,如果您有指向家庭的链接并更改其名称,对人员 NSEntity所做的任何查询都不能包含带有以下查询项的谓词

  

@ “family.name =%@”

它确实会在SQL存储中使用系列名进行查询。但是,在进行此类更改后,以下查询将起作用:

  

@ “家族=%@”

实际上, NSFetchRequest 仍将检索商店中的信息,但由于结构没有改变,它将替换内存中那些检索到的对象,因此后续测试 [姓氏] 将返回更新的名称。

小心,您可以使用嵌套谓词,例如:

  

@ “person.family.name =%@”

只要您可以保证所有具有 person 属性的对象,其系列未被更改,其名称也未被更改。如果不是这样,那么你最多可以打电话

  

@ “person.family =%@”

或者,如果您无法保证所有系列对象都不受影响,则只有

  

@ “人=%@”

当然,另一种方法是每次进行任何更改时系统地 SAVE: NSManagedObjects到持久性存储,因此所有属性都会更新,然后所有上述符号都可以工作。有时候你确实想要阻止储蓄并强迫客户只在他愿意的情况下改变它的文件(想想Word,Excel,图片工具等等)。希望这有帮助。

答案 2 :(得分:0)

如果通过“使用相同的获取请求”,您的意思是使用第一次构建的获取请求的相同实例,那么这并不奇怪。您应用的谓词是“family.name = Doe”。一旦家庭的名字是“小麦”,获取请求的谓词不再匹配它,因为“小麦”!=“Doe”。

要在更改名称后检索系列,您需要使用与新系列名称匹配的谓词创建NSFetchRequest的新实例。

如果通过“使用相同的获取请求”,你的意思是使用使用相同代码构造的不同获取请求,那么我会考虑@ Mundi的答案。