I have a large amount of images that correspond to records in a sqlite db. where should I store them? I have 3 versions of the same image - large, med, thumb sizes. (I don't want to store them in the db table, but reference them instead from each record)
all the images have the same name - each small, med and large image files would all be called "1.jpg" for record 1 in the sqlite table etc... this is mainly because I'm using an image batch resizing program that retains the same file name and creates a new folder.
thanks for any help.
For my cached images, I stored them in TMP folder, you can access using NSTemporaryDirectory.
I don't know if it is good for your cases or if it is good in general but it works quite well
Related
I'm building an application which has a "record" feature which records user interaction over time. As time progresses, I fill an array in memory with "state" objects representing the current state of the user input. A typical recording will result in about 5k of these objects.
I then archive this data using NSKeyedArchiver archiveRootObject: toFile:. This works fine, however the file size is very large (3.5 megs or so). My question is this:
Is there any inherent file-size overhead involved in archiving files? Would I be able to save this data using much less disk space if I were to use SQLite, or even roll my own file format? Or is the only way to reduce the disk size of the data going to be to reduce the bit depth of the numbers I'm storing?
If your concern is performance, Core Data gives you more granularity. You can lazy load and save by parts during app execution vs loading/saving the whole 3.5Mb object graph.
If your concern is file size, this is the binary plist format, and this is the SQLite file format. But more important than the overhead, is how complex is the translation between your object graph and the Core Data model.
You may also be interested in this comparison of speed and performance for several file formats: https://github.com/eishay/jvm-serializers/wiki/ Not sure if everything there has an C, C++ or objective-C implementation.
3.5 MB isn't a very large file. However, if your app has to load or save a 3.5 MB file all the time, then using Core Data is a lot smarter as this allows you to save only the data that has changed and retrieve only the parts that you're interested in -- not the whole thing every time.
If storage is the main concern, there would be little difference b/w sqlite and core data.
I had to store UIViewControllers with state in an app, where I ended up not saving the serialized objects but saving only the most specific properties and creating a class which read that data and re-allocated those objects.
The property map was then stored in a csv [admittedly very difficult to manage, but small like anything] and then compressed.
I'm looking for the best read performance for a bunch (~200) cached 80px by 80px images. A large chuck (~50) will all needed to be accessed at once.
Should I store the uiimages (as binary data) in a plist or using core data?
A couple of basic concepts:
CoreData is probably the worst way to go for the image data, the documentation states that BLOB segments in the store cause massive performance problems.
Use the file system for what it's built for, read / write access of random chunks of data.
The rest depends on how you organize your data, so here are some thoughts:
80x80 is pretty small, you could probably hold 50 or so in memory at a given time.
You need a way to hash the images into some kind of structure so you know which ones to fetch. I would use core data for storing the locations of the images on the file system, and back your view with an NSFetchedResultsController to pull out the list of file names.
Use some in memory data structure to store the UIImage objects, a FIFO queue with a size of 50 would work well here, as it gets a new image from the file system it pops out the oldest one.
Finally you have to know what images you're going to view and stay ahead of it, file system reads won't be super fast, so you'll need to either chunk your reads or stay far enough of your view to avoid lagging. If your view is showing 50, you might want to keep 100 in memory, 50+ 25 previous and 25 next if you're scrolling for example.
A premature optimization:
If read performance is essential, it would be worth while to store the images in "page" sized chunks, such as a zip of 5 or n images that can be read into memory at once, and then split into their corresponding UIImage files.
I have 100s of file which needs to be accessed for displaying the content on iphone. They are all plists.
Which one is faster core data or file access ? which one is secured ?
You have to consider the file size first, a nice rule of thumb found in these boards is, if the file is under 100kB you can store it as an attribute in an entity as a BLOB, if it is greater that that you maybe want to create a ad-hoc entity for it, and in the end if it exceeds 1 MB in size you can access it through the filesystem.
Secondly, you shall evaluate the cost of the operation too, 100 files may appear many but if you access them few times, maybe file access is the way to go, on the other hand if you need that stored information multiple times frequently but you can even create ad hoc entities for Core Data and load the files at start up. And so on.
This is a nice book on Core Data. You can find many guide lines by reading it, but keep in mind also the general guide lines of designing databases.
If they are static files I would recommend pre-loading them into a Core Data SQLite file. That would yield far better performance, especially if you structure your model properly.
My sqlite file has a size of 7MB. I want to reduce its size. How i can do that ? When am simply compressing it will come around only 1.2 MB. Can i compress my mydb.sqlite to a zip file ? If it is not possible, any other way to reduce size of my sqlite file ?
It is possible to compress before hand, but is very redundant. You will compress your binary before distribution, Apple distributes your app through the store compressed and the compression of a compressed file is fruitless. Thus, any work you do to compress beforehand should not have much of an effect on the resulted size of your application
without details of what you are storing in the DB it's hard to give specific advice. The usual generics on DB Design will apply. Normalise your database.. for example
reduce/remove repeating data. If you have text/data that is repeated then store it once, and use key to reference it
If you are storing large chunks of data then you might be able to zip and unzip these in and out of the database in your app code rather than try to zip the DB
In the app I am working on now I was storing about 500 images in Core Data. I have since pulled those images out and store them in the file system now, but in the process I found that the app would crash on the device if I had an array of 500 objects with image data in them. An array with 500 object ids with the image data in those objects worked fine. The 500 objects without the image data also worked fine. I found that I got the best performance with both an array of object ids and image data stored on the filesystem instead of in core data.
The conclusion I came to was that if I had an object in an array that told Core Data I was "using" that object and Core Data would hold on to the data. Is this correct?
Short answer is yes.
The long answer is that it depends on the size of the images. The rule is:
less than 100kb store it in a main table.
less than 1mb store it in a secondary table on the other end of a relationship.
greater than 1mb, store it on disk and reference it via a file path.
So, depending on the size of your files will determine where to store them. Also, keep in mind that UIImage handles caching so you may not need to store the images in an array at all.
Update
Your question is unclear then. You do not need to store the images in an array because A) the image is being held by the cell and; B) UIImage will cache the image for you so it will not be retrieved from disk if it has been accessed lately. So you are forcing the retention of images unnecessarily.
With regard to Core Data itself, it will drop attributes out of memory as needed as well. It will automatically pull them back into memory when accessed. Core Data also caches the data so you should not see any performance issues there either as things are being moved around in memory.