在Core Data数据模型中有效存储相同的数据

时间:2009-10-22 04:21:43

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

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

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

我已经搞砸了创建一个“ImageBlob”实体来存储图像数据并使用关系来做到这一点,但我是Core Data的新手,如果这是正确的方法我不会立刻明白。特别是,我该如何处理以下情况?

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

处理此问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

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

但是,如果您确实有办法有效地执行此操作,则可以创建一个ImageBlob实体来执行您所描述的操作。使用ImageBlob的实体应与imageBlob建立imageBlobsImageBlob关系。 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];
    }
}

答案 1 :(得分:1)

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

至于核心数据的东西,我觉得这样的东西可能会起作用: 然后,创建一个抽象的父实体(Parent)。添加从Parent到名为Image的{​​{1}}的关系,并为删除方法设置“级联”,这样当您删除image时,Parent也会被删除。添加从ImageImage的{​​{1}}或其他任何关系,并为删除方法设置“Nullify”,这样当您删除Parent时,{{1}的图像1}}设置为parent。然后,添加其他实体并将其父级设置为Image