除非我首先访问父类的描述,为什么NSManagedObject关系对象没有正确加载?

时间:2011-01-24 16:51:01

标签: iphone objective-c core-data nsmanagedobject

我正在加载CoreData中的对象列表,如下所示:

- (NSMutableArray *)loadAllPoisFromCache:(BOOL)includeCustom {  
NSFetchRequest *request = [[NSFetchRequest alloc] init];

[request setReturnsObjectsAsFaults:NO];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"PointOfInterest" inManagedObjectContext:managedObjectContext];

NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                          initWithKey:@"sortOrder" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sort]];
[sort release];

if(!includeCustom) {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(custom == %i)",NO];
    [request setPredicate:predicate];
}

[request setEntity:entity];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];

[request release];

return mutableFetchResults;
}

“PointOfInterest”实体是COMPPointOfInterest,它与实体“Location”有一个关系,它是一个COMPLocationEntity。

然后我循环结果:

NSMutableArray *mutableFetchResults = [self loadAllPoisFromCache:YES];

if (mutableFetchResults != nil && [mutableFetchResults count] > 0) {

    NSLog(@"NOTIF_PoisLoaded with data from cache");

    for (COMPPointOfInterest *aPoi in mutableFetchResults) {
        COMPLocationEntity *locBeforePrintingOutPoi = aPoi.locationEntity;
        NSLog(@"Loc class before printing out parent POI = %@", [locBeforePrintingOutPoi class]);
        NSLog(@"Loaded POI %@ from cache %@ and location %@", aPoi.poiId, [aPoi class], [locBeforePrintingOutPoi class]);
        NSLog(@"Loaded POI from cache %@", aPoi);
        COMPLocationEntity *locAfterPrintingOutPoi = aPoi.locationEntity;   
        NSLog(@"Loc class refetched from parent POI after printing out POI = %@", [locAfterPrintingOutPoi class]);
        NSNumber *lat2 = locAfterPrintingOutPoi.latitude;
        NSLog(@"Lat from refetched loc %@", lat2);
        // crash on next line!
        NSNumber *lat = locBeforePrintingOutPoi.latitude;
        NSLog(@"Lat %@", lat);

    }

现在,这就是我被困住的地方,如果你运行它,输出如下:

  

2011-01-24 16:35:41.063 NEC Companion [11959:207] NOTIF_PoisLoaded with cache from cache

     

2011-01-24 16:35:41.064 NEC Companion [11959:207]在打印出父POI之前的Loc类POI = _NSObjectID_48_1

     

2011-01-24 16:35:41.068 NEC Companion [11959:207]从缓存COMPPointOfInterest和位置_NSObjectID_48_1加载POI 1

     

2011-01-24 16:35:41.069 NEC Companion [11959:207]从缓存中加载POI(实体:PointOfInterest; id:0xae19110; data:{       cacheDate =“2011-01-24 16:09:26 +0000”;       custom = 0;       locationEntity =“0xae18ff0”;       logoUrl =“http://192.168.37.213/companion/images/mapicons/es”;       poiId = 1;       sortOrder = 0;   })

     

2011-01-24 16:35:41.071 NEC Companion [11959:207]在打印出POI = COMPLocationEntity之后从父POI重新获取Loc类

     

2011-01-24 16:35:41.072 NEC Companion [11959:207] Lat来自refetched loc 52.460118

     

2011-01-24 16:35:41.072 NEC Companion [11959:207] - [_ NSObjectID_48_1纬度]:无法识别的选择器发送到实例0xae18ff0

我的问题的症结在于,如果我在开始遍历列表时立即从POI中获取“locationEntity”属性,那么该类将作为_NSObjectID_48_1发出,然后我执行NSLog(@“从缓存中加载POI% @“,aPoi);然后我再次获得“locationEntity”属性,最终得到正确的COMPLocationEntity类!

所以看起来调用描述方法正在做一些事情来正确地完全实例化POI ......但是什么?

任何帮助都非常感激。

2 个答案:

答案 0 :(得分:2)

是的,看起来我已经解决了。我的问题确实是locationEntity是一个关系,并在我的查询中添加以下内容会导致对象正确加载,我的位置关系已完全填充。

  

[request setRelationshipKeyPathsForPrefetching:       [NSArray arrayWithObject:@“locationEntity”]];

请参阅http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSFetchRequest_Class/NSFetchRequest.html

答案 1 :(得分:1)

看起来它是错误的 - 在你特别要求它之前,CoreData没有得到数据。

您已指定在创建获取请求时不会在结果中对每个aPoi的属性进行错误处理。这意味着它具有COMPointOfInterest对象的所有属性。

然而,这并不意味着它的所有关系的对象都没有出现故障 - 您的COMPLocationEntity对象是(我假设)一种关系。 CoreData在特别要求之前不会获得这些,并且在此之前将它们标记为故障。因此获得一个非常奇怪的对象名称。当你问一个COMPLocationEntity的属性(在这种情况下,说明*),故障火灾和真实COMPLocationEntity对象加载。

这一行引发了错误:

NSLog(@"Loaded POI from cache %@", aPoi);

核心数据需要一些真实的数据输出你的APol对象,以便去,并从数据库中获取它,使COMPLocationEntity对象。

希望有所帮助。

*通常,在NSManagedObject 上调用描述不会导致错误(故意这样做)。您是否覆盖了类中的描述方法以输出更有用的内容?如果是这样,你就会自己触发故障!