Where to cache remote image files in iOS? - iphone

I am planning to cache the images from a server and use show it as a sort slide show in my App. I would be asynchronously loading the images.
I have two options:
Either to cache the images as a File and use it whenever necessary.
Cache the images objects in memory and use it when ever necessary and write it in to files when Application quits.
Which one would be better?
Please let me know if you you have any kind of suggestions regarding caching images.

Your second approach has 2 major flaws:
If there's too many images then your application will get low memory warning and you'll have to dispose your images from memory anyway
It's also not a good idea to save all images to file on application quit - it is not guaranteed that your saving code will finish on application exit (e.g. if it takes too long system may just terminate your app and your images will be lost)
I'd suggest saving images to files right after you download them and keep in memory reasonable number of images you need to show without visible delay (loading extra images when required and disposing of unnecessary ones)

I would recommend you the first option. Leaves you more flexibility, e.g. when the data size increases the memory size.

I'd do it like this: Have a NSMutableDictionary with the cached images (as UIImage objects). If the image is not in the cache, look whether it's available as a file. If it's not available as a file, load it, put it into your dictionary and also write it to a file.
As for where to write the files to: you can either use the NSTemporaryDirectory() or create a directory inside your NSLibraryDirectory (use NSSearchPathForDirectoriesInDomains to locate it). The later has the advantage/disadvantage that it will be in the iTunes backup (whether that's an advantage or not depends on the use case). Using the Library directory is Apple's recommended way of storing data that is backed up but does not appear in the iTune's file exchange thingy (Documents directory).

I have started using EGOImageView to handle my caching; it's very versatile and handles the intricacies of caching for you.
It works very well for pulling images via http, you can find it on the EGO developer website here
http://developers.enormego.com/

For image caching solution on iOS platform, you might want to consider SDWebImage framework available at: https://github.com/rs/SDWebImage. It is very easy to integrate and takes care of all your image caching worries.: read more about the working here: https://github.com/rs/SDWebImage#readme
We recently picked this up for our app and it works great.

Related

Multiple Image storing and dealing with table view

Despite there are a lot of themes around this topic, I seem very frustrated in the following situation :(
The app downloads and parses a JSON with about 1000 objects, which have in their attributes link for a small image. I need to download (once) these images, store them and use in my TableView as icons.
What is the best way to store such amount of files and to work efficiently with them while displaying the TableView?
I will tell you how will I do it but before I would like to give you a warning about downloading files from the Internet and storing them in your app.
I got one of my apps rejected from Apple lately because I violated rule 2.23 from the App Store Review Guidelines which says:
2.23 Apps must follow the iOS Data Storage Guidelines
or they will be rejected
Since Apple is using iCloud lately you should minimize the traffic that each app will upload and therefore you should not have more than 40MB stored in your Documents folder of your app. They also say (if you read the links I provided):
Data that can be downloaded again or regenerated should be stored in
the /Library/Caches directory.
And since the cache folder can be deleted by the iOS if needed, you should design your app to be prepared to download the images again in case they are gone, so keep this in mind.
Now for my solution, I think downloading 1000 files is too much (even if they are small files). I suggest that you have the files saved in a ZIP file on the server from which you are willing to download and unzip them on your disc once downloaded. This will be much easier and more practical. You can look here to see how to zip and unzip in your app.
After you have your files unzipped I suggest to have a small database (SQLite) from which you can load load the file names, store these names in an array, and then use this array to fill the images in your table in the function cellForRowAtIndexPath.
I hope this helps you. By the way, it is my way to do it but I am not saying it is the "best way" as you are asking :)
Given that you would like to keep these images/data persistent, you now have two options: You can manage them yourself or you can utilize Core Data to help you do it. I recommend Core Data.
If your not familiar with Core Data, you can start reading about it Here. It's a little bit daunting to get started, but once you've run through a tutorial it's extremely straightforward and will make your life much easier.
If you would like store the images yourself, or would like a more efficient Core Data structure, I recommend writing all of your images into your Documents directory as see Here. Then you can just store File path strings in your CD structure or manually in your plist like This.
And finally, for loading them into your TableView you can use those stored image paths to load UIImages with:
[[UIImage alloc] initWithContentsOfFile:filePath];
This would be placed within your:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
function so that you can set the image where you would like.

Create a link on the ios filesystem with Objective-C

I'm trying to create a comic reader app which supports both online reading & off-line reading (by downloading).
I've found MWPhotoBrowser as my image viewer, which supports SDWebImage as the image cache.
My problem is that if some user read little part of a comic on-line, and then they decides to download it for offline reading. Since the already read part is cached by SDWebImage, I don't wanna download them again from the web server. But since user asks to download them locally, I don't wanna keep them on the image cache neither as this will make the downloaded images out of our hand.
Copy the image from the image cache to the place I wanna put is a feasible solution, but it takes storage space. So, what I'm trying to do is cut the image from the image cache to the right place, and then make some soft-link in the image cache. In this way, there should be only one image copy in the storage file system.
You don't want a symbolic (soft) link. A symlink doesn't prevent the original file (in the cache) from being deleted. If the original file is deleted, you'll get an error when you try to open it through the symlink.
You want a hard link. You can create a hard link using -[NSFileManager linkItemAtURL:toURL:error:] or -[NSFileManager linkItemAtPath:toPath:error:]. Take a look at the NSFileManager Class Reference.
If you need to learn more about hard links and symbolic links, you can quickly find a lot of information by searching for “hard link” or “symbolic link” in your favorite search engine.
NOTE FOR FUTURE SEARCHERS
You can create a symbolic link using -[NSFileManager createSymbolicLinkAtURL:withDestinationURL:error:] or -[NSFileManager createSymbolicLinkAtPath:withDestinationPath:error:].

How can I save a html file with external resources using AFNetworking?

I would like to save a .html webpage with AFNetworking, but would also like to save the resources (such as .css files, .js files, images etc) within the webpage so that the whole webpage can be viewed offline.
Is this possible with AFNetworking, and how would I do it? Could a short example be posted please?
Thanks!
AFNetworking is not necessary to do this. Instead, what you want to do is use an NSURLCache subclass that supports disk cacheing (such as Peter Steinberger's fork of SDURLCache). With that in place, just load up a URL using a UIWebView (this may not necessarily have to be displayed to a user), and subsequent loads should use that local cache.
At the very least, do not waste your time trying to write something on your own to download assets on a webpage. This process requires a web browser (which UIWebView qualifies as) to determine everything needed to load.

iphone embedding images in the executable file

When releasing to the application store someone wrote in an offhand comment that you need to avoid embedding your images into the executable.
How do you do that?
I've seen code in various books that suggests encoding images as C byte array constants in the source code, and I can say that that's definitely a bad idea for reasons ranging from inefficient pixel formats to unsalvageable memory. That would qualify as "in the executable file" in a way that bundle resources don't, since bundle resources are packaged alongside the executable rather than within it.
I am not sure if I get you correctly, but maybe he meant accidentally adding image files to the Compile Sources category in your build target? This usually does not happen with images, but i have seen it happening with js files.
Perhaps they meant that you should only include images in the bundle that are essential.
The bundle is essentially read-only so you cannot remove an image from the device that is in the bundle. Therefore placing lots of example images that you expect a user to remove/not want is not a good idea because when the user deletes the images from inside your app no space on the device will be reclaimed.
Of course it is fine to place images in the bundle just make sure that they are required and are not taking up unnecessary space that the user cannot reclaim.

App getting heavy while saving data to iphone directory,,,

I am saving data to iphone directory which i have created, in PNG format,,,but my app getting heavier,
what should I do ?
Seems like the choices are fairly obvious: either delete data from the documents directory that you don't need anymore, or use a file format with more compression than PNG (eg, lossy JPEG). You'll have to make a compromise somewhere, so it's about what's better for you app: more compression on the images, or keeping lossless images but automatically deleting (or offering users the option to manually delete) files older than a certain date, etc.
You are probably not releasing used memory (such as images, view, etc). Try running your application with Build & Analyze.