Обнаружение облегченной миграции основных данных
Я успешно использую облегченную миграцию Core Data. Однако, когда конкретная сущность создается во время миграции, я бы хотел заполнить ее некоторыми данными. Конечно, я мог бы проверять, является ли объект пустым при каждом запуске приложения, но это кажется неэффективным, когда Core Data имеет структуру миграции.
Можно ли определить, когда происходит легкая миграция (возможно, с помощью KVO или уведомлений), или для этого требуется реализация стандартных миграций?
Я пытался использовать NSPersistentStoreCoordinatorStoresDidChangeNotification
, но он не срабатывает, когда происходят миграции.
3 ответа
Чтобы определить, требуется ли миграция, проверьте, совместима ли модель управляемых объектов постоянного координатора магазина с метаданными существующего магазина (адаптировано из " Необходима миграция Apple"):
NSError *error = nil;
persistentStoreCoordinator = /* Persistent store coordinator */ ;
NSURL *storeUrl = /* URL for the source store */ ;
// Determine if a migration is needed
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
URL:storeUrl
error:&error];
NSManagedObjectModel *destinationModel = [persistentStoreCoordinator managedObjectModel];
BOOL pscCompatibile = [destinationModel isConfiguration:nil compatibleWithStoreMetadata:sourceMetadata];
NSLog(@"Migration needed? %d", !pscCompatibile);
Если pscCompatibile
является NO
тогда миграция должна произойти. Чтобы изучить изменения сущности, сравните NSStoreModelVersionHashes
ключ в sourceMetadata
словарь для [destinationModel entities]
:
NSSet *sourceEntities = [NSSet setWithArray:[(NSDictionary *)[sourceMetadata objectForKey:@"NSStoreModelVersionHashes"] allKeys]];
NSSet *destinationEntities = [NSSet setWithArray:[(NSDictionary *)[destinationModel entitiesByName] allKeys]];
// Entities that were added
NSMutableSet *addedEntities = [NSMutableSet setWithSet:destinationEntities];
[addedEntities minusSet:sourceEntities];
// Entities that were removed
NSMutableSet *removedEntities = [NSMutableSet setWithSet:sourceEntities];
[removedEntities minusSet:destinationEntities];
NSLog(@"Added entities: %@\nRemoved entities: %@", addedEntities, removedEntities);
Принятый ответ конвертируется в Swift...
var persistentStoreCoordinator: NSPersistentStoreCoordinator?
var url: URL
do {
let sourceMetadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: url, options: nil)
if let destinationModel = persistentStoreCoordinator?.managedObjectModel {
let compatibile = destinationModel.isConfiguration(withName: nil, compatibleWithStoreMetadata: sourceMetadata)
if !compatibile {
if let versionHashes = sourceMetadata["NSStoreModelVersionHashes"] as? [String: Any] {
let sourceEntities = Set(versionHashes.keys)
let destinationEntities = Set(destinationModel.entitiesByName.keys)
var addedEntities = Set(destinationEntities)
addedEntities.subtract(sourceEntities)
var removedEntities = Set(sourceEntities)
removedEntities.subtract(destinationEntities)
let modelName = (destinationModel.versionIdentifiers.first as? String) ?? ""
NSLog("Core Data requires a migration to model '\(modelName)'...\nAdded: \(addedEntities)\nRemoved: \(removedEntities)")
}
}
}
} catch {
...
}
Как насчет создания подкласса NSManagedObject для этой сущности, а затем переопределения -awakeFromInsert:? Или вы создаете эту сущность в других частях вашего приложения?