Перевод приложения iOS на совершенно новую базовую модель данных

Я унаследовал приложение для iOS, которое должно претерпеть серьезные изменения. В своей текущей форме он использует один UIManagedDocument (не синхронизированный с iCloud, а просто используемый, чтобы избежать шаблонного кода Core Data) для хранения пользовательских данных. Мне нужно внести кардинальные изменения в модель данных, и я хотел бы переключиться на обычный стек Core Data. Существующая кодовая база также была непригодна для использования, поэтому я решил создать новый проект, но с тем же идентификатором приложения, чтобы его можно было использовать как обновление.

Я не знаю, как импортировать данные существующих пользователей в новую модель данных.

Текущая модель имеет 3 основных объекта, и мне нужно только 2 атрибута от каждого из них (остальные старые данные можно выбросить). Я создал новую модель данных, а затем скопировал все файлы старой модели из предыдущего проекта, а также старую модель данных.

Затем я написал класс импортера:

-(BOOL)isImportNeeded
{
    return [[NSFileManager defaultManager] fileExistsAtPath:[[self URLToOldModel] path]];
}

-(NSURL*)URLToOldModel
{
    NSURL* URL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    return [URL URLByAppendingPathComponent:@"Data"];
}

-(UIManagedDocument*)managedDocumentAtPath:(NSString*)path
{
    return [[UIManagedDocument alloc] initWithFileURL:[self URLToOldModel]];
}

-(void)performWithDocument:(void (^)(void))onDocumentReady
{
    if (self.managedDoc.documentState == UIDocumentStateClosed) {
        // I put this code here for debug purposes
        NSError* e = nil;
        if (![self.managedDoc readFromURL:self.managedDoc.fileURL error:&e]) {
            NSLog(@"Couldn't read UIManagedDocument: %@", [e localizedDescription]);
        }
//        [self.managedDoc openWithCompletionHandler:^(BOOL success){
//            if (success)
//                onDocumentReady();
//            else
//                NSLog(@"Could not open document");
//        }];
    }
    else if (self.managedDoc.documentState == UIDocumentStateNormal)
    {
        onDocumentReady();
    }
}

-(void)import
{
    self.managedDoc = [self managedDocumentAtPath:[[self URLToOldModel] path]];
    self.sourceManagedObjectContext = self.managedDoc.managedObjectContext;

    [self performWithDocument:^{ ... }];
}

Этот NSLog выводит следующее: Couldn't read UIManagedDocument: The operation couldn’t be completed. (Cocoa error 134100.) Немного углубившись в словарь ошибки userInfo, я вижу причину ошибки: «Модель, используемая для открытия магазина, несовместима с той, которая использовалась для создания магазина».

Я убедился, что старая модель данных добавлена ​​в проект и находится на этапе сборки «Компилировать источники».

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

-(NSManagedObjectModel*)managedObjectModel
{
    NSString* modelPath = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"momd"];
    modelPath = [modelPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL* modelURL = [NSURL URLWithString:modelPath];
    return [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}

Тем не менее, я все еще получаю ту же ошибку.


person Shinigami    schedule 15.10.2013    source источник


Ответы (1)


Мой друг предложил это, и я использовал его в каждом приложении основных данных, над которым я когда-либо работал - понятия не имею, как это ускользнуло от меня:

self.managedDoc.persistentStoreOptions = @{NSIgnorePersistentStoreVersioningOption: @YES,
                                           NSMigratePersistentStoresAutomaticallyOption: @YES,
                                           NSInferMappingModelAutomaticallyOption: @YES};

Это сделало это.

person Shinigami    schedule 26.10.2013