Почему объект отношения 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 с данными из кэша

2011-01-24 16:35:41.064 NEC Companion[11959:207] Класс Loc перед распечаткой родительского POI = _NSObjectID_48_1

2011-01-24 16:35:41.068 NEC Companion[11959:207] Загрузил POI 1 из кэша COMPPointOfInterest и местоположения _NSObjectID_48_1

2011-01-24 16:35:41.069 NEC Companion[11959:207] POI загружен из кеша (объект: PointOfInterest; id: 0xae19110 ; данные: { 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] Класс Loc обновлен из родительской POI после распечатки POI = COMPLocationEntity

2011-01-24 16:35:41.072 NEC Companion[11959:207] Широта из обновленного местоположения 52.460118

2011-01-24 16:35:41.072 NEC Companion[11959:207] - [широта_NSObjectID_48_1]: нераспознанный селектор отправлен в экземпляр 0xae18ff0

Суть моей проблемы в том, что если я возьму атрибут "locationEntity" из POI сразу же, как только начну перебирать список, класс выйдет как _NSObjectID_48_1, затем я сделаю NSLog(@"Loaded POI from cache %@", апои); и после этого я снова получаю атрибут "locationEntity" и получаю правильный класс COMPLocationEntity!

Таким образом, похоже, что вызов метода описания делает что-то, чтобы полностью правильно создать экземпляр POI... но что?

Любая помощь высоко ценится.


person Kieran    schedule 24.01.2011    source источник


Ответы (2)


Хорошо, похоже, я решил это. Моя проблема действительно заключалась в том, что locationEntity было отношением, и добавление следующего к моему запросу приводит к правильной загрузке объекта с полностью заполненным отношением местоположения.

[запрос setRelationshipKeyPathsForPrefetching: [NSArray arrayWithObject: @"locationEntity"]];

См. http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSFetchRequest_Class/NSFetchRequest.html

person Kieran    schedule 25.01.2011
comment
Привет, Кира, у меня тоже такая же проблема. не могли бы вы сослаться на stackoverflow.com/questions/29010721/, и предоставление мне вашего ценного отзыва. - person Nandha; 12.03.2015

Похоже, это ошибка - CoreData не получает данные, пока вы специально не попросите об этом.

При создании запроса на выборку вы указали, что свойства каждого aPoi не должны указываться в ваших результатах. Это означает, что у него есть все свойства объекта COMPointOfInterest.

Однако это не означает, что все его объекты отношений не ошибочны - ваши объекты COMPLocationEntity являются (я предполагаю) отношениями. CoreData не получит их, пока они специально не будут запрошены, и до тех пор будет помечать их как ошибки. Отсюда и очень странное имя объекта. Когда вы запрашиваете свойство COMPLocationEntity (в данном случае описание*), возникает ошибка и загружается реальный объект COMPLocationEntity.

Ошибка загорается в этой строке:

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

Core Data нужны некоторые реальные данные для вывода вашего объекта aPoi, поэтому он получает их из базы данных и создает объект COMPLocationEntity.

Надеюсь, это поможет.

*Обычно вызов описания для NSManagedObject не вызывает ошибки (это делается намеренно). Вы переопределили метод описания в своем классе, чтобы вывести что-то более полезное? Если это так, вы сами вызываете срабатывание неисправности!

person deanWombourne    schedule 24.01.2011
comment
Привет, Дин, спасибо за быстрый ответ. Я вижу, что выполнение NSLog в POI приведет к загрузке всего, но я не знаю, какое правильное решение, чтобы заставить это работать. Я хочу иметь возможность просто сделать: aPoi.locationEntity.latitude Но это просто взрывается, потому что объект отношения загружается не полностью. Как я могу заставить его действительно получить отношения без необходимости распечатывать все это (что явно является полным взломом :)? - person Kieran; 25.01.2011
comment
О, это вообще не должно ломаться - этого должно быть достаточно, чтобы заставить его извлекать данные :( Можете ли вы добавить трассировку стека к своему вопросу, чтобы мы могли видеть, какую ошибку вы получаете? - person deanWombourne; 25.01.2011