【问题标题】:Detecting a Lightweight Core Data Migration检测轻量级核心数据迁移
【发布时间】:2011-03-02 19:54:52
【问题描述】:

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

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

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

【问题讨论】:

    标签: iphone iphone-sdk-3.0 core-data core-data-migration


    【解决方案1】:

    要检测是否需要迁移,请检查持久存储协调器的托管对象模型是否与现有存储的元数据兼容(改编自 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,则需要进行迁移。要检查实体更改,请将sourceMetadata 字典中的NSStoreModelVersionHashes 键与[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);
    

    【讨论】:

    • @hadronzoo 它总是在我启动应用程序时迁移,不应该只做一次吗?
    • @AhmedZ。不,它只发生一次
    【解决方案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 {
                ...
      }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多