Почему класс не подходит для NSFetchRequest? - PullRequest
0 голосов
/ 28 мая 2010

Я работаю с недокументированным 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

С загрузкой из Fetch Request (и моего собственного экземпляра _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])));

Таким образом, очевидно, что, хотя Организация считает, что это 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, а не DicomStudy с? Я включил DicomStudy.h, поэтому он должен видеть объект во время создания модели, контекста и запроса на выборку.

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

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

-Stephen

Ответы [ 2 ]

1 голос
/ 29 мая 2010

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

Обновление

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

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

И показать вывод.

0 голосов
/ 02 июня 2010

Hooookay,

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

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

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

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

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

-Stephen

...