25

我正在成功使用 Core Data 的自动轻量级迁移。但是,当在迁移期间创建特定实体时,我想用一些数据填充它。当然,我可以在每次应用程序启动时检查实体是否为空,但是当 Core Data 具有迁移框架时,这似乎效率低下。

是否可以检测轻量级迁移何时发生(可能使用 KVO 或通知),或者这是否需要实施标准迁移?

我试过使用NSPersistentStoreCoordinatorStoresDidChangeNotification,但发生迁移时它不会触发。

4

3 回答 3

61

要检测是否需要迁移,请检查持久存储协调器的托管对象模型是否与现有存储的元数据兼容(改编自 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);

如果pscCompatibileNO,则需要进行迁移。要检查实体更改,请将字典中的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);
于 2010-06-12T19:14:56.533 回答
5

接受的答案转换为 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 {
            ...
  }
于 2018-07-20T21:34:34.797 回答
1

为该实体子类化 NSManagedObject,然后覆盖 -awakeFromInsert: 怎么样?或者您是否在应用程序的其他部分创建此实体?

于 2010-09-21T08:28:18.607 回答