Проблема с базовой моделью отображения миграции данных - PullRequest
1 голос
/ 02 декабря 2009

У меня есть приложение для iphone, которое использует Core Data для хранения. Я успешно развернул его, и сейчас я работаю над второй версией. Я столкнулся с проблемой с моделью данных, которая потребует нескольких очень простых преобразований данных во время обновления постоянного хранилища, поэтому я не могу просто использовать модель предполагаемого отображения по умолчанию.

Моя объектная модель хранится в пакете .xcdatamodeld с версиями 1.0 и 1.1 рядом друг с другом. Версия 1.1 установлена ​​как активная версия. Все работает нормально, когда я использую поведение миграции по умолчанию и устанавливаю NSInferMappingModelAutomaticsOption в YES. Мое хранилище sqlite обновлено с версии 1.0 модели, и все хорошо, за исключением, конечно, нескольких необходимых преобразований.

В качестве дополнительного экспериментального шага я добавил новую модель отображения в комплект базовой модели данных и не внес никаких изменений в то, что сгенерировал xcode. Когда я запускаю свое приложение (с более старой версией хранилища данных), я получаю следующее

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'

Что я делаю не так? Вот мой код для получения модели управляемого объекта и координатора постоянного хранилища.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"gti_store.sqlite"]];

    NSError *error;
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                                   configuration:nil 
                                                             URL:storeUrl 
                                                         options:options 
                                                           error:&error]) {
        NSLog(@"Eror creating persistent store coodinator - %@", [error localizedDescription]);
    }    

    return _persistentStoreCoordinator;
}


- (NSManagedObjectModel *)managedObjectModel {

    if(_managedObjectModel == nil) {

        _managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
        NSDictionary *entities = [_managedObjectModel entitiesByName];

        //add a sort descriptor to the 'Foo' fetched property so that it can have an ordering - you can't add these from the graphical core data modeler
        NSEntityDescription *entity = [entities objectForKey:@"Foo"];   
        NSFetchedPropertyDescription *fetchedProp = [[entity propertiesByName] objectForKey:@"orderedBar"];
        NSSortDescriptor* sortDescriptor =  [[[NSSortDescriptor alloc] initWithKey:@"index" ascending:YES] autorelease];
        NSArray* sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
        [[fetchedProp fetchRequest] setSortDescriptors:sortDescriptors];
    }
    return _managedObjectModel;
}

Ответы [ 4 ]

5 голосов
/ 26 апреля 2010

Я не очень тщательно продумал это, это просто наблюдение, потому что у меня возникла та же проблема, и я тоже нашел очень мало ссылок на эту ошибку в Интернете.

В моем случае проблема заключалась в том, что я настроил один из объектов моего приложения для наблюдения

NSManagedObjectContextObjectsDidChangeNotification, например, так

        [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(observeContextSave:)
                                                 name:NSManagedObjectContextDidSaveNotification
                                               object:nil];


- (void) observeContextSave:(NSNotification*) notification {
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];}

Как только я переместил этот код, чтобы он выполнялся после миграции, ошибка исчезла.

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

Обновление: подумав об этом немного больше, я думаю, это происходит потому, что во время миграции создается несколько постоянных хранилищ, что означает, что NSManagedObjectContextDidSaveNotification будет отправлено из контекста с другим постоянным хранилищем в контекст, который отправляется mergeChangesFromContextDidSaveNotification.

4 голосов
/ 16 марта 2010

Во-первых, отключите автоматическую миграцию, если у вас есть картографическая модель, вполне вероятно, что они сталкиваются. Сделав это, подтвердите, что ошибка исчезла.

0 голосов
/ 24 января 2013

Кажется, вы уже исправили это, но стоит упомянуть. У меня тоже была эта ошибка, причина в том, что я получил несколько MOC, уведомленных о mergeChangesFromContextDidSaveNotification, в то время как у них были разные постоянные хранилища (или разные схемы). Они не знали, как обращаться с изменениями, которые не принадлежали их магазинам.

0 голосов
/ 20 сентября 2010

У меня была похожая проблема, когда постоянная инициализация хранилища выполнялась из вторичного потока. После того, как я принудительно инициализировал в первичном потоке, проблема пошла. Weird.

...