Основные данные - хранение изображений (iPhone)

У меня есть приложение, в котором я разрешаю пользователю добавлять изображение для своей учетной записи.

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

Я столкнулся с предложением по дизайну создать объект модели Image и создать отношение 1 к 1 с объектом модели User (так, чтобы связанный объект Image не вызывался, если не требуется). Однако я не уверен, как на практике сохранить изображение и является ли это потенциально фатальным с точки зрения производительности.

Я был бы признателен за любые советы по поводу подхода и подводных камней от любого, кто попробовал это сделать.


person Urizen    schedule 18.01.2010    source источник


Ответы (4)


Правило хранения данных изображения в Core Data следующее:

  • ‹Хранить 100 КБ в связанной сущности (человек, адрес, что угодно).
  • ‹1 МБ хранить в отдельном объекте на другом конце отношения, чтобы избежать проблем с производительностью.
  • # P2 #

Вы можете использовать трансформируемый тип данных для хранения NSImage непосредственно в Core Data. Фактически, вы можете использовать трансформируемый тип данных для хранения всего, что реализует протокол NSCoder.

Лично я бы не стал преобразовывать его в CGImageRef, так как таким образом можно потерять много информации.

person Marcus S. Zarra    schedule 20.01.2010
comment
Я сбит с толку, вы говорите, что не хотите хранить изображение в основном объекте данных, используя трансформируемый тип данных? - person memmons; 10.03.2011
comment
Нет. Я говорю, что в зависимости от размера изображения вы захотите сохранить его либо в отдельном объекте, либо на диске. Большие изображения вызывают проблемы с кешем. - person Marcus S. Zarra; 10.03.2011
comment
В iOS5 есть несколько новых интересных способов избавить вас от неприятностей. Проверьте документацию, это все еще под NDA. - person steipete; 01.09.2011
comment
@steipete Как лучше всего воспроизвести это свойство, чье имя не может быть сказано в iOS ‹5 - person Alexsander Akers; 02.09.2011
comment
@steipete Теперь, когда iOS5 не находится под NDA, я предполагаю, что вы имели в виду новое ... внешнее хранилище для значений атрибутов. Если вы укажете, что значение атрибута управляемого объекта может быть сохранено как внешняя запись, Core Data эвристически решает для каждого значения, следует ли сохранять данные непосредственно в базе данных или сохранять URI в отдельном файле, которым он управляет. для тебя. - person Richard Venable; 04.12.2011
comment
Ссылка для получения Core Data, чтобы решить, что делать с большими активами (allowExternalBinaryDataStorage), находится здесь: developer.apple.com/library/mac/documentation/Cocoa/Reference/ - person nevan king; 13.04.2012
comment
@RichardVenable Я использовал это для хранения изображений в нескольких приложениях, и, похоже, у него есть проблемы. Вы успешно его использовали? Какой у вас опыт с этим? - person Philippe Sabourin; 18.04.2012
comment
К вашему сведению, внешнее хранилище не работает на iOS. Это флаг только для настольных компьютеров. - person Marcus S. Zarra; 19.04.2012
comment
Я использовал флаг внешнего хранилища в одном небольшом приложении, и, похоже, оно работало нормально, но я думаю, по словам Маркуса, оно ничего не делает. Думаю, это означает, что фотографии, которые я сохраняю, просто сохраняются в моей базе данных как большие капли. Я бы хотел, чтобы Apple сказала мне это! - person Richard Venable; 19.04.2012
comment
Это небольшая сноска в документации, шокировала меня, когда я тоже ее нашел. - person Marcus S. Zarra; 19.04.2012
comment
Вы имеете в виду UIImage, а не NSImage? - person ; 24.05.2012

Прошло время с тех пор, как был задан этот вопрос, но я хочу поделиться своим опытом по этой проблеме.


Я бы не рекомендовал вам хранить изображения в своей БД, если их количество не ограничено. Вы должны иметь в виду, что когда-нибудь вы добавите новую версию модели данных, и вам придется перейти со старой БД на новую при обновлении приложения. Это требует времени. Чем больше у вас файл БД, тем больше времени требуется на перенос.

Если вы хотите хранить изображения в БД, убедитесь, что вы не добавили постоянное хранилище в application: didFinishLaunchingWithOptions: метод UIApplicationDelegate. iOS завершит работу вашего приложения, если миграция не завершится в течение XX секунд.

person Eldar Markov    schedule 02.07.2012
comment
Большое спасибо +1 за этот комментарий :-) - person PeterK; 31.07.2012
comment
Можете ли вы опубликовать ссылку на надежный источник на комментарий, который вы сделали о iOS, о прекращении работы вашего приложения, если миграция не будет завершена за 30 секунд? - person Pavan; 09.11.2014

Ловушка: вы можете получить огромную, сложную в обращении базу данных sqlite. Вы действительно хотите, чтобы ваши пользователи загружали на сервер файл размером несколько МБ за один шаг? Что делать, если сотовая связь прерывается на несколько секунд?

Я думаю, было бы лучше, если бы вы использовали Core Data для управления своими изображениями и их состоянием загрузки (загружено: да или нет). Таким образом, вы можете загружать изображения, если они подходят для рабочего процесса вашего приложения. Хорошо, это продлится немного дольше из-за множества подключений. Но я думаю, что это более чистый подход ...

Когда вы думаете об iTunes, когда говорите о резервных копиях: ваша локальная папка «Документы» iPhone все равно синхронизируется.

person Stefan    schedule 19.01.2010
comment
Спасибо за ответ. Я могу пойти по пути простого сохранения пути в виде строки, а затем рассчитывать на то, что iTunes предоставит резервную копию файла изображения (при сохранении других данных, связанных с учетной записью, на удаленном сервере). - person Urizen; 19.01.2010

У вас должен быть a, тогда вы можете сделать что-то вроде этого:

CGImageRef imageRef = uiImage.CGImage;
CGDataProviderRef dataProvider = CGImageGetDataProvider(imageRef);
NSData *imageData = (NSData*)CGDataProviderCopyData(dataProvider);
[managedObject setValue:imageData forKey:@"data"];

Где managedObject - это ваш основной объект изображения данных, а @ "data" - имя двоичного свойства. Вам также может потребоваться сохранить формат изображения, чтобы впоследствии десериализовать изображение.

Другой вариант - сохранить образ на диск и сохранить путь в основных данных.

person Elfred    schedule 19.01.2010
comment
также отпустите imageData, когда закончите. - person Elfred; 19.01.2010
comment
Также попробуйте использовать трансформируемый атрибут: разработчик. apple.com/mac/library/documentation/Cocoa/Conceptual/ - person Nimrod; 19.01.2010
comment
Извините, я знаю, что это может показаться основным вопросом, но как вы делаете (и что подразумевается под) сохранением формата изображения? Я раньше не приходил в голову с этой идеей. - person Urizen; 19.01.2010
comment
Я имею в виду сохранение того факта, что изображение является jpg или png (или каким-либо другим форматом). Эта информация понадобится вам при получении данных изображения из базы данных, чтобы выбрать правильного поставщика данных для преобразования его в CGImageRef. - person Elfred; 19.01.2010
comment
Спасибо, Эльфред. Очень полезный ответ. - person Urizen; 19.01.2010