Is it a good idea to store pictures / images in SQLite DB from the App? - iphone

Some discussions in Stackoverflow say that storing the picture in DB is a bad idea (a because overtime, the number of images get large & may lead to app crash). So, either
a. the image can be stored in the iPhone itself & only its location can be stored in the DB
Potential Issue: The image might get removed (outside of the app) & the app might not be able to load them the next time
b. the image can be shrunk to a small size (say, 100*100 pixels) and stored in the DB
Potential Issue: will size be an issue if the image is shrunk to just 100x100pixels?
c. Doing both (a) & (b). So, small versions of the images will be stored in the DB and then, retrieved & displayed in the App, whereas, if the user chooses to see the original version of the image (whose probability is low), then that'll be fetched from the local directory & shown.
Your suggestions please? In my opinion, (c) seems a good option to go in for, in case (a) has the potential issue mentioned.

It really depends on where the images are coming from. Are they being downloaded from the Internet (or imported from the user's library / camera) after the user installs the app, or are they bundled with the app from the App Store?
If the images are being downloaded / imported, the best solution is to store images in the filesystem following the recommendations in http://developer.apple.com/library/ios/#qa/qa1719/_index.html
Basically, if the images cannot be replaced or recreated, store them in the <Application_Home>/Documents directory and do not set the Do Not Backup attribute. These items will be backed up to iCloud, and this data does persist for at least some amount of time even if the app is deleted from the device. (Remember that your users do not have unlimited iCloud space. Be responsible.)
-However-
If the images are bundled with the app, the best solution is to import them directly into your Xcode project and reference them from there. This way you know they are always available even if the user deletes and reinstalls the app.
I would definitely stay away from storing image data in the databased whenever possible. There are simply better, more efficient ways in most any scenario.

Related

Why is saving UIImage data to UserDefaults ill advised?

I am wondering why storing user profile images as Data to user defaults is ill advised. The reason being: I have already created an app that has some people using it. The app requires that users create a profile, on which they can upload up to 6 profile pictures. The images get pushed to my back end and also are stored as Data to the app's user defaults.
I've read that it is better to save these images to the document directory and save the file path as a string to user defaults. Why is this exactly? Is it such a big deal that I should take the time to write code that will convert images saved as Data to user defaults on already existing devices to images saved to the document directory?
The "why" is easy. The UserDefaults is not a database. It's just a plist file. Either the whole thing is loaded into memory at once or it isn't. If it is, there are all your UIImage data objects sitting in memory. Memory is limited and images are big. Plus you waste time during loading and saving.
The "is it such a big deal" part is a matter of opinion. In my own opinion, yes, it is. That's because I've gone through this process, and I was glad I did. Yes, it's a pain writing migration code, but once you've done it you just leave it in place and your app is now handling data saving correctly forever after.

How to make iOS app cache ALL request responses?

I'm starting to work on an app which will include in quite a few places data that I will download from my server each time user is asking to view them. Then, when user opens app again without any internet connection, app should let him view any content it previously downloaded, just loading it from the cache. The point of this is that the content changes from time to time and user needs to be able to see the last downloaded version if he can't connect to the server.
Problem is, I can set the cache to a certain size on disk, but I have to store ALL the content no matter the size. I suppose I'd have to set cache disk size to make it bigger when it's running out of space. What is a good way to do this?
P.S. Not sure if this is relevant, but I was thinking about trying AFNetworking for this project (previously I used ASIHTTPRequest).
If you're using NSURLCache as an on-disk cache, you can check the disk usage with currentDiskUsage. If this is approaching diskCapacity, you can increase it using setDiskCapacity. You should perform this check before you attempt to write to the cache.
I have worked on same type of project, I used AFNetworking and according to me storing the data in local database is better option then caching it... and at the time when user starts app just have one service call which just checks the database version. If its old version replace database and handle the case if network fails by displaying the older version.

Should I save images in database or in a folder?

I want to store some photos that I take from a web service to my phone for the case when I don't have internet connectivity. I am storing data to a database but i have a question: should I store in the database the URL of the photo and the photo in a folder, or store the image in the database? The volume of photos shouldn't be great; something like 200-300 small pics, at approx 30-40kB each.
If you already have a database, i would organize my photos in database with only the path to the photo. And the photos can be stored on memorycard or on local disk.
The basic rule of thumb is to put big data objects like images right onto the disk and only reference the URLs. This might come in handy for loading/processing the images anyway.
30-40 kB per image is not that much, but then I'd consider 6-12 MB for the database quite extensive, especially it's probably the majority of your database volume.
I'm not real familiar with iOS. But my understanding is that it supports XML files. If the database is just being used to store the paths (instead of images), why not use an xml file to store the paths?
If you need the db, with small images, I don't see it being a problem if the phone is just using it. Either way, I don't think it'll be an issue. Someone else can probably give you a better answer as far as efficiency. That's outside my jurisdiction.
Store all the pics in document folder, and when there is no internet connection get them from document folder of your iPhone.

Better way of updating images bundled with the app

In our iOS app we have close to a hundred image files in resources bundle. Now we want to make them network based since the images may change (updated/no longer needed/additions) at any time. We are debating at what approach would be optimal. From what I have read, I understand that the resource bundle will not be editable on the device. So, when I start the app, I will check from the server if there are any image updates. If so, I will download the changed images and then save them to documents directory. Then in the app, for every image, I will basically have to check if it is in the resources bundle, then grab it from there. Else pick it from documents directory and display it.
Another approach is I don't have anything in the resources folder, I download all images on app launch from the server and store them to documents directory and then on, download the changed files at subsequent app launch. Here I am eliminating the check on resources folder if an image is present or not and my app bundle size would be reduced.
The third approach would be to copy the files from my resources directory to the documents directory on first launch and thereafter continue from documents directory.
Any suggestions on what would be a better approach or all of them would be similar from the performance point of view?
IMO, option three offers the best balance between eliminating needless code and preloading as much data as possible. You don't want to make the user wait for 100 image downloads when the app starts the first time, so pre-load as many as possible. The copy code is simple and will only be used once. So that eliminates the runtime checks you'd have to do with the other options.
No worries, performance will not be an issue, unless you use a particularly unwise image lookup algorithm.
Filesystem traversal should be pretty fast for such a small amount of files.
Before implementing something yourself, I would recommend looking at something off the shelf for Image Caching. Namely EGOImageView from EnormEgo.
I have used it in several applications which are dependent on grabbing images from URLs. It handles everything for you, you just set up a 'background' image for it to show while it goes about it's business of grabbing the URL based image in the background. The second time you use it, it's available immediately. Definitely gets my vote for ease of use...
p.s. it's free to use

How to store a very large image on an iPhone/iPad

What's the best way to store a very large image for an iOS app? I want an app to be able to view images that might be hundreds of megabytes, perhaps as much as a gigabyte as jpeg. I need to be able to store the image and retrieve selected areas for display.
Currently the images are cut into 512x512 pixel tiles and stored as jpeg files in a directory tree with tens of thousands of tiles (actually an image pyramid including downsamples).
Ignoring the question of displaying the image, I'm interested in the most efficient, manageable way to store this data on the device: files, like they currently are, in an sqlite database or something else?
Second part to the question. Is there a limit to the amount of data an app can store, or can an app keep importing data up to the storage limit of the device. I'm asking here about data that an app imports after it's installed.
The solution to this is to pre tile the enormous image so the tiles can be quickly retrieved from the file system on an as needed basis. One problem with very large images is that most solutions require the whole image to be rendered into a context, consuming vast amounts of memory. On a system like iOS, where memory is limited, the way to solve this is to use a library like libjeg or libjpegturbo to render an image a line at a time, then save the pixels into a raw file. The downside to doing this directly is that when you need one tile, you need to jump all over the file system finding each row of a tile. Thus a better solution is to not only incrementally scan, but incrementally tile too. You can use mmap to map the file into just the area you need, so you can really minimize memory consumption. That said, you can thrash the Unified Buffer Queue on iOS so badly the app crashes, or even the whole system!
If you are curious about how to implement the above solution, there is a freely available project on github - PhotoScrollerNetwork - that does all the above.
A sample from Apple: PhotoScroller
What about splitting into parts. Then it can be gathered by your application if needed