核心数据延迟加载的问题

时间:2011-02-10 22:19:22

标签: cocoa core-data objective-c-2.0

核心数据懒惰地加载对象,并且一旦您尝试引用它们就应该引入任何对象。但是我遇到了这个方案的几个问题。

目标C 2.0对关系(集合)中对象的快速枚举可能会失败(因为集合中的对象尚未加载),并且在触摸由核心数据管理的对象的成员之前不会调用awakeFromFetch。

例如,如果我在NSManagedObject的子类中有关系,例如:

@property (retain) NSSet* clips;

在获取该对象的实例后,如果我尝试使用如下的快速枚举:

for (PClip* clip in self.clips) {  
    // do something with the clip  
}

永远不会执行循环体。在调试器中,您可以看到剪辑集(运行时_NSFaultingMutableSet的实例)最初为空。

或者说我有一个从持久状态派生的剪辑对象的非持久成员:

@property (retain) NSString* filename

我将其与使用awakeFromFetch方法同步,但是在第一次调用对象的某个持久成员之前不会调用awakeFromFetch,因此如果某些代码在加载对象之前尝试访问此非持久值,则它还不会被定义(即将是零)。

在获取请求上使用setReturnsObjectsAsFaults:方法似乎没有帮助。它似乎不会强制获取附加到获取对象的所有对象树。

在使用对象之前,确保加载对象的最佳方法是什么?为什么快速枚举无法导致加载对象集?

4 个答案:

答案 0 :(得分:1)

替换

时会发生什么
for (PClip* clip in clips) {  
    // do something with the clip  
}

for (PClip* clip in self.clips) {  
    // do something with the clip  
}

?您不能使用像实例变量这样的coredata值,您必须使用setter和getter。因为getter将从核心数据中获取值。

然后尝试为文件名创建一个getter,以便在第一次访问该对象时创建该对象。

根据我的经验,通常没有必要在awakeFromFetch中做任何事情。

答案 1 :(得分:1)

我认为默认情况下会加载托管对象的属性 要加载关系,您可以执行以下操作:
NSArray *relationshipKeys = [NSArray arrayWithObject:@"clips"];
[fetchRequest setRelationshipKeyPathsForPrefetching:relationshipKeys];

答案 2 :(得分:0)

似乎有用(虽然看起来有点像黑客)是强制从顶级对象的awakeFromFetch方法遍历完整的对象树。

例如:

-(void) awakeFromFetch {
    // accessing the count of each relationship forces the set of objects to load  
    self.clips.count;  
    for (PClip* clip in self.clips) {  
        // access a persistent member of each object, which will cause
        // its awakeFromFetch method to be called  
        clip.pathURL;    
    }
}

答案 3 :(得分:0)

@CuriousKea只是提示,使用FRC时,不应该在awakeFromFetch中设置关系。因为设置关系将导致FRC再次被通知,并且FRC委托将被调用两次。它伤害了表现。