ios 我应该如何在我的 Core Data 数据库中存储 UIImages?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3908910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:52:48  来源:igfitidea点击:

How should I store UIImages within my Core Data database?

iphoneobjective-ccore-dataios

提问by Asad Khan

I am developing an application which demands around 100 images or maybe more to be pre-inserted into the Core Data database along with other related information.

我正在开发一个应用程序,它需要大约 100 张图像或更多图像与其他相关信息一起预插入到 Core Data 数据库中。

Now I can easily add other data by just writing a few lines of code but for UIImages I am unsure how to do it without writing a lot of code. I was wondering: is there anyway to do this easily, or if there isn't what's the best way to achieve this with the least amount of effort.

现在我只需编写几行代码就可以轻松添加其他数据,但是对于 UIImages,我不确定如何在不编写大量代码的情况下进行添加。我想知道:无论如何,是否可以轻松地做到这一点,或者是否没有以最少的努力实现这一目标的最佳方法。

Also, is it okay to store images in a Core Data database or should we only only save the addresses of images on the local file system?

另外,是否可以将图像存储在 Core Data 数据库中,还是应该只将图像的地址保存在本地文件系统中?

回答by Brad Larson

Storing images within a Core Data database is pretty easy to do. You just need to mark your image attribute as a transformable one and create a subclass of NSValueTransformer. Within that subclass, add code like the following:

在 Core Data 数据库中存储图像非常容易。您只需要将图像属性标记为可转换属性并创建 NSValueTransformer 的子类。在该子类中,添加如下代码:

+ (Class)transformedValueClass 
{
    return [NSData class]; 
}

+ (BOOL)allowsReverseTransformation 
{
    return YES; 
}

- (id)transformedValue:(id)value 
{
    if (value == nil)
        return nil;

    // I pass in raw data when generating the image, save that directly to the database
    if ([value isKindOfClass:[NSData class]])
        return value;

    return UIImagePNGRepresentation((UIImage *)value);
}

- (id)reverseTransformedValue:(id)value
{
    return [UIImage imageWithData:(NSData *)value];
}

For your transformable attribute, specify this subclass's name as the Value Transformer Name.

对于您的可转换属性,将此子类的名称指定为值转换器名称。

You can then create an NSManagedObject subclass for the entity hosting this image attribute and declare a property for this image attribute:

然后,您可以为托管此图像属性的实体创建一个 NSManagedObject 子类,并为此图像属性声明一个属性:

@property(nonatomic, retain) UIImage *thumbnailImage;

You can read UIImages from and write UIImages to this property and they will be transparently changed to and from NSData to be stored in the database.

您可以从此属性读取 UIImages 并将 UIImages 写入此属性,它们将透明地更改为 NSData 或从 NSData 更改为存储在数据库中。

Whether or not to do this depends on your particular case. Larger images probably should not be stored in this manner, or at the least should be in their own entity so that they are not fetched into memory until a relationship to them is followed. Small thumbnail images are probably fine to put in your database this way.

是否这样做取决于您的具体情况。较大的图像可能不应该以这种方式存储,或者至少应该在它们自己的实体中,以便在遵循与它们的关系之前它们不会被提取到内存中。以这种方式将小缩略图图像放入数据库中可能很好。

回答by Bjinse

A good example of the image transformer as described above is in the iPhoneCoreDataRecipes demo application.

上面描述的图像转换器的一个很好的例子是在 iPhoneCoreDataRecipes 演示应用程序中。

回答by Chris Gummer

Apple does provide some advice around BLOBs: Large Data Objects (BLOBs)

Apple 确实提供了一些关于 BLOB 的建议: 大数据对象 (BLOB)

If your application uses large BLOBs ("Binary Large OBjects" such as image and sound data), you need to take care to minimize overheads. The exact definition of "small", "modest", and "large" is fluid and depends on an application's usage. A loose rule of thumb is that objects in the order of kilobytes in size are of a "modest" sized and those in the order of megabytes in size are "large" sized. Some developers have achieved good performance with 10MB BLOBs in a database. On the other hand, if an application has millions of rows in a table, even 128 bytes might be a "modest" sized CLOB (Character Large OBject) that needs to be normalized into a separate table.

In general, if you need to store BLOBs in a persistent store, you should use an SQLite store. The XML and binary stores require that the whole object graph reside in memory, and store writes are atomic (see “Persistent Store Features”) which means that they do not efficiently deal with large data objects. SQLite can scale to handle extremely large databases. Properly used, SQLite provides good performance for databases up to 100GB, and a single row can hold up to 1GB (although of course reading 1GB of data into memory is an expensive operation no matter how efficient the repository).

A BLOB often represents an attribute of an entity—for example, a photograph might be an attribute of an Employee entity. For small to modest sized BLOBs (and CLOBs), you should create a separate entity for the data and create a to-one relationship in place of the attribute. For example, you might create Employee and Photograph entities with a one-to-one relationship between them, where the relationship from Employee to Photograph replaces the Employee's photograph attribute. This pattern maximizes the benefits of object faulting (see “Faulting and Uniquing”). Any given photograph is only retrieved if it is actually needed (if the relationship is traversed).

It is better, however, if you are able to store BLOBs as resources on the filesystem, and to maintain links (such as URLs or paths) to those resources. You can then load a BLOB as and when necessary.

如果您的应用程序使用大型 BLOB(“二进制大型对象”,例如图像和声音数据),您需要注意尽量减少开销。“小”、“中等”和“大”的确切定义是可变的,取决于应用程序的使用情况。一个宽松的经验法则是,大小为千字节的对象具有“适度”大小,而大小为兆字节的对象为“大”大小。一些开发人员已经在数据库中使用 10MB BLOB 获得了良好的性能。另一方面,如果应用程序在一个表中有数百万行,即使 128 字节也可能是一个“中等”大小的 CLOB(字符大对象),需要规范化到一个单独的表中。

通常,如果您需要将 BLOB 存储在持久存储中,则应该使用 SQLite 存储。XML 和二进制存储要求整个对象图驻留在内存中,并且存储写入是原子的(请参阅“持久存储功能”),这意味着它们不能有效地处理大型数据对象。SQLite 可以扩展以处理非常大的数据库。如果使用得当,SQLite 可以为高达 100GB 的数据库提供良好的性能,单行最多可以容纳 1GB(当然,无论存储库多么高效,将 1GB 数据读入内存都是一项昂贵的操作)。

BLOB 通常表示实体的属性——例如,照片可能是 Employee 实体的属性。对于小到中等大小的 BLOB(和 CLOB),您应该为数据创建一个单独的实体并创建一对一关系来代替属性。例如,您可以创建 Employee 和 Photo 实体,它们之间具有一对一的关系,其中从 Employee 到 Photo 的关系替换了 Employee 的照片属性。这种模式最大限度地发挥了对象故障的好处(参见“故障和唯一性”)。任何给定的照片只有在实际需要时才会被检索(如果关系被遍历)。

但是,如果您能够将 BLOB 作为资源存储在文件系统上,并维护指向这些资源的链接(例如 URL 或路径),那就更好了。然后,您可以在必要时加载 BLOB。