3

I planning on building an app whose main content are images. Basically, it is going to have multiple menus using UITableViews, whose cells are going to have only an image. When you click the cell, you'll be pushed to a simple view with that image and another one, wich has the rest of the detailed content.

This is all quite easy to do, my questions is about optimization. It's gonna have LOTs of content (Maybe 1k rows) and It's gonna display images in the UITableView, so Core Data is a must (given it's lazy loading and several other optimizations)

My question is: What's best, to store the image in the Core Data db (as NSData) or to just store the name of the image? What I'm imagining is if I store the name of the resource, For each row in the UITableView the device must go fetch that image, process it finally display it. When scrolling trough them (wich is expected to happen A LOT) we would have lots of fetching images. If I store them in Core Data, it would be as simple as taking that info and using it as if it where an image.

The benefits of storing the images in Core Data comes with the normal withdraws of storing blobs in a db. I don't know how much of a problem this would be in Core Data (My experience in dbs comes mainly from MySQL)

On the other hand, tough my "common sense" dictates saving just the name and fetching the images as they're needed its gonna take more time if they're requested more, I'm not sure how much of a performance hit would this be. Is there a "best way" to store them? Just the name and then call pathForResourse:ofType:or (if it's faster) pathForResourse:ofType:inDirectory: on the mainBundle, store the URI, or other form of pointing to it.

edit: The application will have static content shipped with the application and the user won't be able to modify this content in any way. (at least in version 1.0)

Daniel
  • 1,321
  • 12
  • 25
  • Quite small, 20kb each tops? They're images that contain text and symbols, black & white – Daniel Jul 24 '12 at 19:01
  • If they're not too big then I wouldn't worry too much about it, except that you might want to put the blobs in a separate object so you can load the metadata separately. – tc. Jul 25 '12 at 12:04
  • I found also more convenient, when dealing with UITableViews with thumbnail, to store them in DB. There's a whole world apart with storing only file name location, you soon encounter the problem of lazy loading, and it is not easy to deal with. I published an app recently with image+db mechanism, and nobody is complaining about performance. – Leonardo Jul 26 '12 at 15:49
  • Uhm...I didn't read carefully, if you plan to store images in the bundle itself for distributing within your app, there's no point in having them also in db. – Leonardo Jul 26 '12 at 15:55
  • That's the thing, I could just pack them in the db and not in the bundle. And It'll be easier too, if I ever want to lets say sell a more complete db using in-app purchases – Daniel Jul 29 '12 at 07:00

3 Answers3

5

From the Core Data Release Notes for iOS v5.0:

Small data values like image thumbnails may be efficiently stored in a database, but large photos or other media are best handled directly by the file system. You can now specify that the value of a managed object attribute may be stored as an external record—see setAllowsExternalBinaryDataStorage:. When enabled, Core Data heuristically decides on a per-value basis if it should save the data directly in the database or store a URI to a separate file which it manages for you. You cannot query based on the contents of a binary data property if you use this option.

The setAllowsExternalBinaryDataStorage: essentially does what you described "...just store the name of the image..."

Also refer to these other questions:

  1. CoreData : store images to DB or not?
  2. Core data images from desktop to iphone
  3. Provide example for why it is not advisable to store images in CoreData?
Community
  • 1
  • 1
Michael
  • 577
  • 6
  • 13
  • I recently ask the same question, asking for concrete example. You could add to the list also http://stackoverflow.com/questions/10848147/provide-example-for-why-it-is-not-advisable-to-store-images-in-coredata – Leonardo Jul 26 '12 at 15:44
1

you will get a great optimization from just using the name of the file...

if you re-use a file ... you wont have to store it in the database twice, or alternately have a model object just to represent that file as a relationship.

You could do some profiling and check... but I assume that just a name would be ideal. also you could do a little work to make something similar to -imageNamed that caches the images for you, and you will only have to make one UIImage for each file, wherever it exists in your program.

Grady Player
  • 14,399
  • 2
  • 48
  • 76
  • Thanks, I'm concern in RAM memory optimization rather than use of storing. And I'm almost never reusing the images. Can you explain further your `-imageNamed:` idea? – Daniel Jul 24 '12 at 17:41
  • 2
    If your concerned about memory management, you can use an NSCache to store the images. NSCache will "temporarily store objects with transient data that are expensive to create" and objects will be "discarded if memory is tight. If discarded, their values will have to be recomputed again when needed." See: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSCache_Class/Reference/Reference.html – Michael Jul 24 '12 at 17:47
  • 1
    -imageNamed will only make a brand new UIImage if it doesn't have one cached, you could use NSCache or your own implementation to do something similar. I guess NSHashMap is out on IOS – Grady Player Jul 24 '12 at 17:58
1

Don't save the images in core data. You can save the information pertaining the images in an organized matter in core data, but keep the images ordered in a supporting files section in your project. Or if you are downloading the images, you can cache them in your images section of the app and simply update the information for the images in core data.

A Salcedo
  • 6,378
  • 8
  • 31
  • 42