Я унаследовал приложение для 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];
}
Тем не менее, я все еще получаю ту же ошибку.