Как я должен хранить UIImages в моей базе данных Core Data?

Я занимаюсь разработкой приложения, для которого требуется предварительно вставить около 100 или даже больше изображений в базу данных Core Data вместе с другой соответствующей информацией.

Теперь я могу легко добавить другие данные, просто написав несколько строк кода, но для UIImages я не уверен, как это сделать без написания большого количества кода. Мне было интересно: есть ли в любом случае это легко сделать, или нет лучшего способа добиться этого с наименьшими усилиями.

Кроме того, можно ли хранить изображения в базе данных Core Data или мы должны только сохранять адреса изображений только в локальной файловой системе?

3 ответа

Решение

Хранить изображения в базе данных 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];
}

Для вашего преобразуемого атрибута укажите имя этого подкласса как Имя преобразователя значения.

Затем можно создать подкласс NSManagedObject для объекта, на котором размещен этот атрибут изображения, и объявить свойство для этого атрибута изображения:

@property(nonatomic, retain) UIImage *thumbnailImage;

Вы можете читать UIImages из и записывать UIImages в это свойство, и они будут прозрачно изменены в и из NSData для хранения в базе данных.

То, стоит ли это делать, зависит от вашего конкретного случая. Большие изображения, вероятно, не должны храниться таким образом, или, по крайней мере, должны быть в их собственной сущности, чтобы они не извлекались в память до тех пор, пока не будут соблюдены отношения с ними. Небольшие миниатюрные изображения, вероятно, можно поместить в вашу базу данных таким образом.

Хорошим примером преобразователя изображения, как описано выше, является демонстрационное приложение iPhoneCoreDataRecipes.

Apple предоставляет несколько советов относительно больших двоичных объектов: большие объекты данных (большие двоичные объекты)

Если ваше приложение использует большие большие двоичные объекты ("большие двоичные объекты", такие как изображения и звуковые данные), необходимо позаботиться о том, чтобы минимизировать накладные расходы. Точное определение "маленький", "скромный" и "большой" является гибким и зависит от использования приложения. Эмпирическое правило гласит, что объекты размером порядка килобайт имеют "скромный" размер, а объекты размером порядка мегабайт - "большой". Некоторые разработчики достигли хорошей производительности с 10 МБ BLOB в базе данных. С другой стороны, если приложение имеет миллионы строк в таблице, даже 128 байтов могут быть CLOB "скромного" размера (крупный символьный объект), который необходимо нормализовать в отдельную таблицу.

В общем, если вам нужно хранить большие двоичные объекты в постоянном хранилище, вам следует использовать хранилище SQLite. Для хранения XML и двоичных файлов требуется, чтобы весь граф объектов находился в памяти, а записи в хранилище были атомарными (см. "Функции постоянного хранилища"), что означает, что они неэффективно работают с большими объектами данных. SQLite может масштабироваться для работы с очень большими базами данных. При правильном использовании SQLite обеспечивает хорошую производительность для баз данных объемом до 100 ГБ, а одна строка может содержать до 1 ГБ (хотя, конечно, чтение 1 ГБ данных в память является дорогостоящей операцией, независимо от того, насколько эффективен репозиторий).

BLOB часто представляет атрибут объекта - например, фотография может быть атрибутом объекта Employee. Для BLOB малого и среднего размера (и CLOB) необходимо создать отдельный объект для данных и создать отношение "один к одному" вместо атрибута. Например, вы можете создать сущности "Сотрудник" и "Фотография" с взаимно-однозначным отношением между ними, где отношение "Сотрудник" к "Фотография" заменяет атрибут фотографии сотрудника. Этот шаблон максимизирует преимущества повреждения объекта (см. "Неисправность и уникальность"). Любая данная фотография извлекается, только если она действительно необходима (если пересекаются отношения).

Однако лучше, если вы сможете хранить большие двоичные объекты как ресурсы в файловой системе и поддерживать ссылки (например, URL-адреса или пути) на эти ресурсы. Затем вы можете загрузить BLOB по мере необходимости.

Другие вопросы по тегам