Ответ 1
Один вариант (и, как правило, предпочтительный при работе в SQL) заключается в том, чтобы записать изображение в файл в системе и сохранить путь (или какой-либо другой идентификатор) в базе данных.
Я создал SQLite DB, который в настоящее время отлично читает и записывает NSString
. Я также хочу сохранить изображение в базе данных и напомнить его позже. Я немного поработал с использованием NSData
и кодирования изображения, но я не совсем уверен, что такое синтаксис для того, что я хочу делать. Любые фрагменты кода или примеры будут с благодарностью оценены.
Мой текущий процесс выглядит следующим образом:
UIImagePickerController
→ Пользователь выбирает изображение из фотографий → selectedImage устанавливается в экземпляр UIImageView
→ Теперь я хочу взять это изображение и сохранить его в DB
Я должен упомянуть, что этот вызов в конечном итоге будет заменен вызовом удаленного сервера. Не уверен, что это имеет значение с точки зрения производительности.
Один вариант (и, как правило, предпочтительный при работе в SQL) заключается в том, чтобы записать изображение в файл в системе и сохранить путь (или какой-либо другой идентификатор) в базе данных.
Вам нужно будет преобразовать UIImage, размещенный в вашем UIImageView, в двоичный BLOB для хранения в SQLite. Для этого вы можете использовать следующее:
NSData *dataForImage = UIImagePNGRepresentation(cachedImage);
sqlite3_bind_blob(yourSavingSQLStatement, 2, [dataForImage bytes], [dataForImage length], SQLITE_TRANSIENT);
Это создаст представление PNG вашего изображения, сохранит его в экземпляре NSData и привяжет байты из NSData как BLOB для второго аргумента в вашем SQL-запросе. Используйте UIImageJPEGRепредставление в приведенном выше для хранения в этом формате, если хотите. Вам нужно будет добавить столбец BLOB в соответствующую таблицу в вашей базе данных SQLite.
Чтобы получить это изображение, вы можете использовать следующее:
NSData *dataForCachedImage = [[NSData alloc] initWithBytes:sqlite3_column_blob(yourLoadingSQLStatement, 2) length: sqlite3_column_bytes(yourLoadingSQLStatement, 2)];
self.cachedImage = [UIImage imageWithData:dataForCachedImage];
[dataForCachedImage release];
Рекомендация Apple заключается не в том, чтобы хранить BLOB в базах данных SQLite, превышающих ~ 2 килобайта.
SQLite организует базы данных на страницах. Каждая страница имеет размер 4 килобайта. Когда вы читаете данные из файла базы данных SQLite, он загружает эти страницы в внутренний кеш страниц. На iPhone я думаю, что этот кеш по умолчанию имеет размер 1 мегабайт. Это делает чтение смежных записей очень быстрым, потому что они, вероятно, уже будут в кэше страниц.
Когда SQLite считывает вашу запись базы данных в память, она считывает всю запись и все страницы, которые она занимает. Поэтому, если ваша запись содержит BLOB, она может занимать много страниц, и вы будете выталкивать существующие страницы из кеша и заменять их вашими блоками записи BLOB.
Это не так уж плохо, если вы просто просматриваете и загружаете все свои BLOBS, чтобы что-то делать с ними (покажите их, например). Но если вы сказали, что выполнили запрос, в котором вы хотели получить некоторые данные, расположенные в той же строке, что и BLOB, этот запрос будет намного медленнее, чем если бы запись не содержала большой BLOB.
Итак, как минимум вы должны хранить данные BLOB в отдельной таблице. Например:
CREATE TABLE blobs ( id INTEGER PRIMARY KEY, data BLOB );
CREATE TABLE photos ( id INTEGER PRIMARY KEY, name TEXT, blob_id INTEGER,
FOREIGN KEY(blob_id) REFERENCES blobs(id) );
Или еще лучше сохранить данные BLOB как файлы вне базы данных SQLite.
Обратите внимание, что может быть возможно настроить размер кеша страницы с помощью инструкций SQL PRAGMA (если вы не используете CoreData).
Написание образа на SQLite DB
if(myImage != nil){
NSData *imgData = UIImagePNGRepresentation(myImage);
sqlite3_bind_blob(update_stmtement, 6, [imgData bytes], [imgData length], NULL);
}
else {
sqlite3_bind_blob(update_stmtement, 6, nil, -1, NULL);
}
Чтение из SQLite DB:
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(init_statement, 6) length:sqlite3_column_bytes(init_statement, 6)];
if(data == nil)
NSLog(@"No image found.");
else
self.pictureImage = [UIImage imageWithData:data];
Лучшей практикой является сжать изображение и сохранить его в базе данных или файловой системе. Если вы не заботитесь о разрешении изображения, вы можете пойти и даже изменить размер изображения, используя:
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
После этого вы можете использовать UIImageJPEGRepresentation
для jpeg-изображений со значением "0" для максимального сжатия. Или вы можете использовать UIImagePNGRepresentation
для png-изображений
вы должны сначала написать изображение в файловой системе. а затем возьмите путь изображения и сохраните этот путь изображения (URL) как ТЕКСТ в sqlite.