Detecting a Lightweight Core Data Migration

后端 未结 3 1155
走了就别回头了
走了就别回头了 2020-12-12 19:56

I\'m using Core Data\'s automatic lightweight migration successfully. However, when a particular entity gets created during a migration, I\'d like to populate it with some d

相关标签:
3条回答
  • 2020-12-12 20:16

    To detect whether a migration is needed, check to see if the persistent store coordinator's managed object model is compatible with the existing store's metadata (adapted from Apple's 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);
    

    If pscCompatibile is NO, then a migration will need to occur. To examine the entity changes, compare the NSStoreModelVersionHashes key in the sourceMetadata dictionary to the [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);
    
    0 讨论(0)
  • 2020-12-12 20:16

    The accepted answer converted to 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 {
                ...
      }
    
    0 讨论(0)
  • 2020-12-12 20:30

    What about subclassing NSManagedObject for that entity, and then overriding -awakeFromInsert:? Or are you creating this entity in other parts of your app?

    0 讨论(0)
提交回复
热议问题