Ручная миграция схемы базовых данных без предупреждения «документ изменен»? - PullRequest
4 голосов
/ 19 декабря 2008

Модель данных для моего приложения на основе документов Core Data (только 10.5) находится в инфраструктура, поэтому автоматическое обновление схемы с использованием отображения основных данных модель не работает Похоже, что механизм основных данных не находит подходящих моделей данных или картографической модели, когда они не в основной комплект приложения. Таким образом, вместо использования автоматического миграция, я запускаю миграцию вручную в configurePersistentStoreCoordinatorForURL:ofType:... по моему NSPersistenDocument подкласс (код ниже). Я мигрирую постоянный сохранить во временный файл, а затем перезаписать существующий файл, если миграция удалась. Документ затем представляет ошибку с сообщение "Файл этого документа был изменен другим приложением так как вы открыли или сохранили ". когда я пытаюсь сохранить. Как и другие на этом Список указали, это связано с моей модификацией файл документа "за его спиной". Я пытался обновить документ дата изменения файла, как показано ниже, но затем я получаю диалоговое окно с сообщением об ошибке с сообщением «Расположение документа« test.ovproj »нельзя определяется ". Когда я пытаюсь сохранить. Я менее уверен в причине этого ошибка, но обмен одного ненужного сообщения (в данном случае) на другое не совсем то, что я собирался.

Может кто-нибудь предложить какое-нибудь руководство? Есть ли способ вручную обновить схема для постоянного хранилища документа без запуска одного из эти (в этом случае ненужные) предупреждения?

код для обновления хранилища данных в моих подклассах -configurePersistentStoreCoordinatorForURL:ofType:...:

if(upgradeNeeded) {
           NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:VUIModelBundles() orStoreMetadata:meta];

           if(sourceModel == nil) {
               *error = [NSError errorWithDomain:VUIErrorDomainn ode:VUICoreDataErrorCode localizedReason:BWLocalizedString(@"Unable to find original data model for project.")];
               return NO;
           }

           NSManagedObjectModel *destinationModel = [self managedObjectModel];

           NSMigrationManager *migrationManager = [[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel];
           NSMappingModel *mappingModel = [NSMappingModel mappingModelFromBundles:VUIModelBundles() forSourceModel:sourceModel destinationModel:destinationModel];
           if(mappingModel == nil) {
               *error = [NSError errorWithDomain:VUIErrorDomain code:VUICoreDataErrorCode localizedReason:BWLocalizedString(@"Unable to find mapping model to convert project to most recent project format.")];
               return NO;
           }

           @try {
               //move file to backup
               NSAssert([url isFileURL], @"store url is not a file URL");

               NSString *tmpPath = [NSString tempFilePath];
               id storeType = [meta objectForKey:NSStoreTypeKey];
               if(![migrationManager migrateStoreFromURL:url
                                                    type:storeType
                                                 options:storeOptions
                                        withMappingModel:mappingModel
                                       toDestinationURL:[NSURLfileURLWithPath:tmpPath]
                                         destinationType:storeType
                                      destinationOptions:storeOptions
                                                   error:error]) {

                   return NO;
               } else {
                   //replace old with new
                   if(![[NSFileManager defaultManager] removeItemAtPath:[url path] error:error] ||
                      ![[NSFileManager defaultManager] moveItemAtPath:tmpPath toPath:[url path] error:error]) {
                       return NO;
                   }

                   // update document file modification date to prevent warning (#292)
                   NSDate *newModificationDate = [[[NSFileManager defaultManager] fileAttributesAtPath:[url path] traverseLink:NO] bjectForKey:NSFileModificationDate];
                   [self setFileModificationDate:newModificationDate];
               }
           }
           @finally {
               [migrationManager release];
           }
       }
   }

   return [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:storeOptions error:error];

Ответы [ 3 ]

1 голос
/ 19 ноября 2009

Остерегайтесь FSExchangeObjects ()! Он не поддерживает все типы томов, см. BSupportsFSExchangeObjects. Я ищу замену сам. Похоже, что опция MoreFilesX - FSExchangeObjectsCompat или 10.5 - FSReplaceObjects ().

1 голос
/ 19 декабря 2008

Я не сталкивался с этой конкретной ситуацией, но у меня есть несколько догадок. Во-первых, вместо использования -removeItemAtPath: и -moveItemAtPath: когда вы хотите переключать файлы, используйте вместо этого функцию FSExchangeObjects (). NSDocument использует FSRefs для отслеживания файла, и если вы не используете FSExchangeObjects (), он поймет, что смотрит на совершенно другой файл.

Во-вторых, вы можете вручную установить управляемую объектную модель документа, переопределив -managedObjectModel, в частности, используя метод + mergedModelFromBundles: для загрузки моделей из вашей платформы. В соответствии с документами, он должен по умолчанию объединять любые модели в основном комплекте и во всех связанных инфраструктурах, так что это должно быть необходимо только для динамически загружаемых пакетов. Не знаю, почему это не работает для вас, но я не пробовал это. Чтобы выяснить, какие пакеты искать, NSBundle + метод bundleForClass: ваш друг.

0 голосов
/ 22 февраля 2018

10 лет спустя ... Я столкнулся с той же проблемой, и с новым API для NSDocument вы можете обновить fileModificationDate документа с новой датой обновленного файла после выполнения миграции

migrate()
if let newModificationDate = try? NSFileManager.defaultManager().attributesOfItemAtPath(url.path!)[NSFileModificationDate] as? NSDate {
    self.fileModificationDate = newModificationDate
}

после этого вы можете позвонить super.configurePersistentStoreCoordinatorForURL...

Это потому, что NSDocument устанавливает дату изменения файла еще до вызова readFromURL:ofType См. Поток сообщений инициализации документа

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...