【问题标题】:Storing identical data efficiently in a Core Data data model在 Core Data 数据模型中有效地存储相同的数据
【发布时间】:2010-09-07 05:20:49
【问题描述】:

我有一个包含多个实体的数据模型,每个实体都有几个不同的属性来存储图像数据。这些都是小图像,我需要将它们存储在持久存储中,而不是作为外部文件。

虽然我可以将图像数据存储在 Binary 或 Transformable 属性中,但用户很可能会为这些属性中的两个或多个指定相同的图像,因此我宁愿存储每个唯一图像的副本而不是复制图像数据。

我已经搞砸了创建一个“ImageBlob”实体来存储图像数据并使用关系来执行此操作,但我是 Core Data 的新手,如果这是正确的方法,我并不会立即明白.尤其是以下情况如何处理?

  • 我希望我在多个实体中的所有图像属性都使用相同的“图像数据存储”,以便每个图像 blob 只存储一个实例
  • 我需要确保如果没有对象正在使用数据存储中的图像,则将其删除

最好的处理方法是什么?

【问题讨论】:

    标签: objective-c cocoa core-data data-modeling


    【解决方案1】:

    我的第一个问题是您打算如何识别两个对象何时使用相同的图像?您可以存储和查询图像上的属性以确定您设置的图像是否已经存在?那在计算上有多昂贵?如果花费大量时间,您最终可能会针对存储进行优化并影响性能。

    但是,如果您确实有办法有效地执行此操作,则可以创建一个 ImageBlob 实体来执行您所描述的操作。使用ImageBlobs 的实体应该与ImageBlob 具有imageBlobimageBlobs 关系。 ImageBlob 应该与名称成反比关系,例如 users

    在您的代码中,当您想要重用 ImageBlob 时,只需执行以下操作即可:

    NSManagedObject *blob = // get the image blob
    NSManagedObject *user = // get the user
    [user setValue:blob forKey:@"imageBlob"]; // do this if it uses a single image
    [[user mutableSetValueForKey:@"imageBlobs"] addObject:blob]; // do this if it uses multiple images
    

    您需要考虑的另一个问题是如何处理不再需要的 blob。据推测,您想删除任何未使用的图像。为此,您可以注册您的应用程序委托或NSPersistentDocument 子类(取决于您的应用程序是否基于文档)以获取NSManagedObjectContextObjectsDidChangeNotification 通知。每当托管对象上下文发生变化时,您都可以像这样删除任何不需要的图像:

    - (void)managedObjectContextObjectsDidSave:(NSNotification *)notification {
        NSManagedObjectContext *managedObjectContext = [notification object];
    
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        [fetchRequest setEntity:[NSEntity entityWithName:@"ImageBlob" inManagedObjectContext:managedObjectContext]];
        [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"users.@count == 0"];
        NSArray *unusedBlobs = [managedObjectContext executeFetchRequest:fetchRequest error:nil]; // Don't be stupid like me; catch and handle the error
        [fetchRequest release];
    
        for (NSManagedObject *blob in unusedBlobs) {
            [managedObjectContext deleteObject:blob];
        }
    }
    

    【讨论】:

    • 谢谢,这是一个有用的建议。这不是一个完整的解决方案,但我接受了答案。
    【解决方案2】:

    您可以向 Image 实体添加一个名为 md5 的唯一属性,以确保您只存储一次相同的图像。

    至于核心数据的东西,我认为这样的事情可能会奏效: 然后,创建一个抽象父实体 (Parent)。在ParentImage 之间添加一个名为image 的关系,并将删除方法设置为“级联”,这样当您删除Parent 时,Image 也会被删除。添加从ImageParent 的关系,称为parent 或其他任何内容,并将删除方法设置为“Nullify”,以便在删除Image 时,Parent 的图像设置为nil。然后,添加您的其他实体并将其父级设置为 Parent

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      相关资源
      最近更新 更多