我正在成功使用Core Data的自动轻量级迁移。但是,当在迁移期间创建特定实体时,我想用一些数据填充它。当然,我可以在每次应用程序启动时检查实体是否为空,但是当Core Data具有迁移框架时,这似乎效率低下。
是否可以检测轻量级迁移何时发生(可能使用KVO或通知),还是需要实现标准迁移?
我已尝试使用NSPersistentStoreCoordinatorStoresDidChangeNotification
,但在迁移发生时不会触发。
答案 0 :(得分:58)
要检测是否需要迁移,请检查持久性存储协调器的托管对象模型是否与现有商店的元数据兼容(改编自Apple的Is Migration Necessary):
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);
答案 1 :(得分:2)
接受的答案转换为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 {
...
}
答案 2 :(得分:1)
如何为该实体继承NSManagedObject,然后覆盖-awakeFromInsert:?或者您是否在应用的其他部分创建了此实体?