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数据库中是否可以,或者我们是否只保存本地文件系统上的图像地址?
3 个解决方案
#1
55
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.
对于transformable属性,请将此子类的名称指定为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:
然后,您可以为托管此image属性的实体创建NSManagedObject子类,并声明此image属性的属性:
@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并将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.
是否这样做取决于您的具体情况。较大的图像可能不应该以这种方式存储,或者至少应该存在于它们自己的实体中,以便在跟随它们之间的关系之前不将它们提取到存储器中。小缩略图图像可能很好地以这种方式放入您的数据库。
#2
11
A good example of the image transformer as described above is in the iPhoneCoreDataRecipes demo application.
如上所述的图像变换器的一个很好的例子是在iPhoneCoreDataRecipes演示应用程序中。
#3
8
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.
如果您的应用程序使用大型BLOB(“二进制大对象”,如图像和声音数据),则需要注意尽量减少开销。 “小”,“适度”和“大”的确切定义是流动的,取决于应用程序的用法。一个宽松的经验法则是大小为千字节的对象是“适度”大小的,而大小为兆字节的对象是“大”大小的。一些开发人员在数据库中使用10MB BLOB取得了良好的性能。另一方面,如果应用程序在表中有数百万行,则即使128字节也可能是“适度”大小的CLOB(字符大对象),需要将其标准化为单独的表。
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).
通常,如果需要将BLOB存储在持久性存储中,则应使用SQLite存储。 XML和二进制存储要求整个对象图驻留在内存中,并且存储写入是原子的(参见“持久存储功能”),这意味着它们不能有效地处理大型数据对象。 SQLite可以扩展以处理极大的数据库。正确使用,SQLite为高达100GB的数据库提供了良好的性能,单行可以容纳1GB(尽管当然,无论存储库的效率如何,将1GB的数据读入内存都是一项昂贵的操作)。
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).
BLOB通常表示实体的属性 - 例如,照片可能是Employee实体的属性。对于小到适度大小的BLOB(和CLOB),您应该为数据创建一个单独的实体,并创建一个一对一的关系来代替该属性。例如,您可以创建Employee和Photograph实体,它们之间具有一对一的关系,其中Employee与Photograph之间的关系取代了Employee的photograph属性。这种模式最大化了对象故障的好处(参见“Faulting and Uniquing”)。只有在实际需要时才会检索任何给定的照片(如果遍历关系)。
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作为资源存储在文件系统上,并维护到这些资源的链接(例如URL或路径),那就更好了。然后,您可以在必要时加载BLOB。
#1
55
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.
对于transformable属性,请将此子类的名称指定为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:
然后,您可以为托管此image属性的实体创建NSManagedObject子类,并声明此image属性的属性:
@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并将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.
是否这样做取决于您的具体情况。较大的图像可能不应该以这种方式存储,或者至少应该存在于它们自己的实体中,以便在跟随它们之间的关系之前不将它们提取到存储器中。小缩略图图像可能很好地以这种方式放入您的数据库。
#2
11
A good example of the image transformer as described above is in the iPhoneCoreDataRecipes demo application.
如上所述的图像变换器的一个很好的例子是在iPhoneCoreDataRecipes演示应用程序中。
#3
8
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.
如果您的应用程序使用大型BLOB(“二进制大对象”,如图像和声音数据),则需要注意尽量减少开销。 “小”,“适度”和“大”的确切定义是流动的,取决于应用程序的用法。一个宽松的经验法则是大小为千字节的对象是“适度”大小的,而大小为兆字节的对象是“大”大小的。一些开发人员在数据库中使用10MB BLOB取得了良好的性能。另一方面,如果应用程序在表中有数百万行,则即使128字节也可能是“适度”大小的CLOB(字符大对象),需要将其标准化为单独的表。
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).
通常,如果需要将BLOB存储在持久性存储中,则应使用SQLite存储。 XML和二进制存储要求整个对象图驻留在内存中,并且存储写入是原子的(参见“持久存储功能”),这意味着它们不能有效地处理大型数据对象。 SQLite可以扩展以处理极大的数据库。正确使用,SQLite为高达100GB的数据库提供了良好的性能,单行可以容纳1GB(尽管当然,无论存储库的效率如何,将1GB的数据读入内存都是一项昂贵的操作)。
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).
BLOB通常表示实体的属性 - 例如,照片可能是Employee实体的属性。对于小到适度大小的BLOB(和CLOB),您应该为数据创建一个单独的实体,并创建一个一对一的关系来代替该属性。例如,您可以创建Employee和Photograph实体,它们之间具有一对一的关系,其中Employee与Photograph之间的关系取代了Employee的photograph属性。这种模式最大化了对象故障的好处(参见“Faulting and Uniquing”)。只有在实际需要时才会检索任何给定的照片(如果遍历关系)。
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作为资源存储在文件系统上,并维护到这些资源的链接(例如URL或路径),那就更好了。然后,您可以在必要时加载BLOB。