Почему класс не подходит для NSFetchRequest?

Я работаю с недокументированным API (Osirix), и у меня есть родственный вопрос тому, который я опубликовал здесь.

У меня возникли проблемы с загрузкой объектов из контекста управляемого объекта.

С загрузкой из API, используя свой экземпляр _context и _model

2010-05-28 14:05:13.588 OsiriX[44012:a0f] Entity: Study
2010-05-28 14:05:13.589 OsiriX[44012:a0f] EntityClassName: DicomStudy
2010-05-28 14:05:13.589 OsiriX[44012:a0f] ClassName: DicomStudy

С загрузкой из запроса на выборку (и моего собственного экземпляра _context и _model)

2010-05-28 14:19:09.956 rcOsirix[44431:7a03] Entity: Study
2010-05-28 14:19:09.957 rcOsirix[44431:7a03] EntityClassName: DicomStudy
2010-05-28 14:19:09.958 rcOsirix[44431:7a03] ClassName: NSManagedObject

вывод, заданный:

NSLog(@"Entity: %@",[[item entity] name]);
NSLog(@"EntityClassName: %@", [[item entity] managedObjectClassName]);
NSLog(@"ClassName: %s", class_getName(object_getClass([item class])));

Таким образом, очевидно, что хотя Entity и думает, что это DicomSeries, это не так. Это просто NSManagedObject. В DicomSeries есть некоторые «жестко закодированные» материалы KVC, с которыми я столкнулся с проблемой в своем другом вопросе.

Я в этой теме рассуждаю иначе - с загрузкой объектов.

Ниже приведен их код:

- (NSManagedObjectModel *)managedObjectModel
{
    if (managedObjectModel) return managedObjectModel;

    NSMutableSet *allBundles = [[NSMutableSet alloc] init];
    [allBundles addObject: [NSBundle mainBundle]];
    [allBundles addObjectsFromArray: [NSBundle allFrameworks]];

    managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: [NSURL fileURLWithPath: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"/OsiriXDB_DataModel.mom"]]];
    [allBundles release];

    return managedObjectModel;
}

- (NSManagedObjectContext *) managedObjectContextLoadIfNecessary:(BOOL) loadIfNecessary
{
    NSError *error = nil;
    NSString *localizedDescription;
    NSFileManager *fileManager;

    if( currentDatabasePath == nil)
        return nil;

    if (managedObjectContext)
        return managedObjectContext;

    if( loadIfNecessary == NO) return nil;

    fileManager = [NSFileManager defaultManager];

    [persistentStoreCoordinator release];

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: self.managedObjectModel];

    managedObjectContext = [[NSManagedObjectContext alloc] init];
    [managedObjectContext setPersistentStoreCoordinator: persistentStoreCoordinator];

    NSURL *url = [NSURL fileURLWithPath: currentDatabasePath];

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error])
    {
        NSLog(@"********** managedObjectContextLoadIfNecessary FAILED: %@", error);
        localizedDescription = [error localizedDescription];
        error = [NSError errorWithDomain:@"OsiriXDomain" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error, NSUnderlyingErrorKey, [NSString stringWithFormat:@"Store Configuration Failure: %@", ((localizedDescription != nil) ? localizedDescription : @"Unknown Error")], NSLocalizedDescriptionKey, nil]];
    }

    [[managedObjectContext undoManager] setLevelsOfUndo: 1];
    [[managedObjectContext undoManager] disableUndoRegistration];

    // This line is very important, if there is NO database.sql file
    [self saveDatabase: currentDatabasePath];

    return managedObjectContext;
}

Это мой код:

NSManagedObjectModel* DataModule::managedObjectModel()
{
if (_managedObjectModel) return _managedObjectModel;

    NSMutableSet *allBundles = [[NSMutableSet alloc] init];
    [allBundles addObject: [NSBundle mainBundle]];
    [allBundles addObjectsFromArray: [NSBundle allFrameworks]];

_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: [NSURL fileURLWithPath: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"/OsiriXDB_DataModel.mom"]]];

    [allBundles release];

return [_managedObjectModel retain];
}

...
        NSError *error = nil;
        [_storeCoordinator release];

        _storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel()];

        _context = [[NSManagedObjectContext alloc] init];
        [_context setPersistentStoreCoordinator: _storeCoordinator];

        NSURL *url = [NSURL fileURLWithPath: [[NSString alloc] initWithCString:_DBPath.c_str()]];

        if (url == nil) { [pool release]; _loadLock = false; return nil; }

        if (![_storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error])
        {
            NSLog(@"********** managedObjectContextLoadIfNecessary FAILED: %@", error);
            NSString *localizedDescription = [error localizedDescription];
            error = [NSError errorWithDomain:@"OsiriXDomain" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error, NSUnderlyingErrorKey, [NSString stringWithFormat:@"Store Configuration Failure: %@", ((localizedDescription != nil) ? localizedDescription : @"Unknown Error")], NSLocalizedDescriptionKey, nil]];

            //Exit Failure
            [pool release]; _loadLock = false; return nil;
        }

        [[_context undoManager] setLevelsOfUndo: 1];
        [[_context undoManager] disableUndoRegistration];
...

Я включаю все те же фреймворки.... но _allBundles даже не используется для создания managedObjectModel, поэтому я не знаю, что он должен делать, кроме как загружать их в память, чтобы mom мог просматривать их во время загрузки.

Полностью потерян.

Помощь!

Почему объекты, возвращаемые моим запросом FetchRequest с одним и тем же объектом, получаются как NSManagedObjects, а не DicomStudys? Я включаю DicomStudy.h, поэтому он должен видеть объект во время создания модели, контекста и запроса на выборку.

[request setEntity: [[managedObjectModel() entitiesByName] objectForKey:@"Study"]];

Заранее спасибо,

-Стивен


person Stephen Furlani    schedule 28.05.2010    source источник


Ответы (2)


Первый вопрос: в вашей модели вы указываете Core Data использовать ваш подкласс DicomStudy или он по-прежнему установлен на NSManagedObject (по умолчанию)?

Обновлять

Хорошо, затем измените третью строку логирования на следующую:

NSLog(@"ClassName: %@", [item class]);

И показать результат.

person Marcus S. Zarra    schedule 29.05.2010
comment
Спасибо за ответ, ммм, да? Насколько я могу судить. img.photobucket.com/albums/v177/maethalion/ Классы импортируются из фреймворка, я не думаю, что это должно иметь значение - или, по крайней мере, различие, которое не вызывает ошибки или предупреждения. Я не уверен, как я могу сказать модели, чтобы она указывала на эти конкретные классы. Кажется, что имя класса сущностей установлено правильно, но оно не создает ссылку во время компиляции или что-то в этом роде. Я не могу найти ничего подобного в IB, где я могу сказать, чтобы он использовал этот конкретный заголовочный файл/класс. - person Stephen Furlani; 01.06.2010
comment
Я получаю тот же NSManagedObject для класса. - person Stephen Furlani; 02.06.2010

ура,

Я чувствую себя гигантским дерьмом, отвечая на каждый мой вопрос, ну да ладно.

Итак, ответ заключается в том, что фреймворк, который я включал, не имел скомпилированного исходного кода. BenT на форумах разработчиков Apple упомянул, что исходный код необходимо скомпилировать. .. поэтому я посмотрел на импортируемый Framework, и оказалось, что он копирует только заголовочные файлы и ничего не компилирует.

Это было сделано (я думаю, так как я не получил ответа от разработчиков этого фреймворка), потому что фреймворк предназначался для использования как часть плагина для основного программного обеспечения. Поскольку архитектура подключаемого модуля загружает все скомпилированные классы, наличие только заголовков в Framework предотвратило objc[1378]: Class BLAH is implemented in both X and Y. One of the two will be used. Which one is undefined. ошибки «забавного времени».

Итак, похоже, мне придется либо включить исходный код, либо создать новый фреймворк из их исходного кода.

Спасибо Маркусу за помощь. Я надеялся, что это не просто проблема «RTFM», так как я занимаюсь разработкой для платформы Apple только с ноября 2009 года. Я еще не успел изучить CoreData...

-Стивен

person Stephen Furlani    schedule 02.06.2010