Disk Backed Image Cache for UIImageView in AFNetworking - ios

I'm looking to swap out the AFImageCache used by default in the UIImageView+AFNetworking category for something that's disk based and that can managed a little more accurately (something like NSURLCache). Unfortunately, since UIImageView+AFNetworking is a category and not a subclass, I can't just override af_sharedImageCache with a sublclass of UIImageView OR another category.
Is there any other way to achieve this functionality without copying and pasting most of UIImageView+AFNetworking into my own subclass?

The SDWebImage project provides a similar UIImageView category, but offers both in-memory (using NSCache) and on-disk (using NSFileManager) caching. I'd recommend just using that when you need to cache to disk.
The downside to this implementation is that your network requests won't go through your AFHTTPClient subclass, so depending on what your needs are you might need to implement your own operation queue, authentication, etc. If you're just using it for something basic, like displaying avatar images in a table view, it should be fine.
If that downside bothers you, an alternate idea would be to use SDImageCache (included in the SDWebImage project) to cache the images, and download them yourself using AFNetworking.
Finally, note that AFNetworking has built-in support for NSURLCache, and if you create one it will cache your images to disk. However, image caching is typically used for showing lots of images in a UIScrollView, and NSURLCache doesn't have good enough performance for smooth scrolling.

I have a fork of AFNetworking that includes file cache in the NSCachesDirectory.
You can find it here: https://github.com/andyast/AFNetworking_FileCache
There is a branch that is compatible with V1.3.3 if you need that as well.

Related

SDWebimage vs HanekeSwift's

There are many caching libraries available in iOS. The most popular library is SDWebImage for caching images. There is one image cache library is HanekeSwift’s for image cache.
My question is What is main difference between SDWebImage and HanekeSwift’s if both are working same? In Which case we use SDWebImage or HanekeSwift’s?
There are few difference between SDWebImage and Haneke. So it depends on user's choice with which Caching Library they want to go.
Here are few:-
SDWebImage:-
1) Categories for UIImageView, UIButton, MKAnnotationView adding web image and cache management
2) A guarantee that the same URL won't be downloaded several times
3) An asynchronous memory + disk image caching with automatic cache expiration handling
Haneke:-
1) Generic cache with out-of-the-box support for UIImage, NSData, JSON and String
2) Zero-config UIImageView and UIButton extensions to use the cache, optimized for UITableView and UICollectionView cell reuse
SDWebImageCache:
Haneke:
Find various feature listing in below image to identify difference between all of them:-
Hope it helps you to distinguish all of them

Networking optimization for UITableView

i'm writing a super simple photo sharing app for practice using parse.com as my server.
i have a tableview that just shows photos a user has uploaded to the server. if nothing is persisted and this guy has a million photos uploaded to the server, what would be the best way to fetch the photos?
I know that the simple way is to make one request on viewdidload and store everything in memory before persisting it. but is there a better way? ideally i could pull photos in batches, and as the user scrolled, it would pull new photos. perhaps there is a library you know of that helps with this?
If you don't want to do the entire thing yourself, you should use SDWebImage
A typical code example looks like
[imageView sd_setImageWithURL:[NSURL URLWithString:#"https://graph.facebook.com/olivier.poitrey/picture"]
placeholderImage:[UIImage imageNamed:#"avatar-placeholder.png"]
options:SDWebImageRefreshCached];

asynchronous request of images by url for scrollview ios

I wanted to know how it is possible to make asynchronous request of images, and display them in a scroll view in a way that I can scroll the images without making requests for each images. I read some threads that gave me some ideas, so I think that I have to stock the urls in an array, and then I don't know what to do. If someone can explain to me ? or have a concrete idea on how to do this ?
NSScreencast has a video that does something similar. It is also a good video to learn about blocks too.
http://nsscreencast.com/episodes/10-fun-with-blocks
in order to load images asynchronously there are many options. The best approach is to create a different thread and fetch the url.
Sometimes its better to used tested and trusted apis available. I will suggest you to use SDWebImage
This will not only help you to load images asynchronously but also provides the caching mechanism. Which you will later or sooner user in you app development.
Its easy to use. Happy Coding :)

Calling [UIImage imageWithData:xxx] multiple times

My model comes from Core Data.
My beans have images stored in the model as NSData.
To display my images, I need to do :
[UIImage imageWithData:bean.imageData]
Is it OK if I do that everywhere ? I mean, from view #1 I display image by creating [UIImage imageWithData:], then I go on view #2 where I need to display the same image, but I only pass the bean between the 2 views, so I recreate the UIImage with [UIImage imageWithData].
I am wondering whether it takes too many CPU or memory if I do this... Do I need to manage a cache myself ? I think this might be quite common use case with CoreData so is there a common pattern to handle this ?
imageWithData will not cache your image (as per the docs, the only UIImage method to cache is imageNamed)
Here is an algorithm for caching images, though.
In answer to your question, imageWithData is a bit slow, so, no you probably don't want to do this all over the place. You'd probably want to do some caching for maximum performance (or at least if you're likely to retrieve the same image repeated during a give session with the app). NSCache, like HalR suggested, is a great solution for that.
Furthermore, if the images are huge, you might not want to store them in CoreData at all, but rather store them in your Documents folder, and only store the filename path in CoreData. It's surprising how much slower it is to retrieve the image from your database and then use imageWithData is than it is to use imageWithContentsOfFile. Admittedly, if you're doing cacheing, you'll suffer this performance hit less often, but still, if you're retrieving lots of separate images, the difference is observable. With thumbnail images, though, it's less of an issue. Everyone draws this line in a different place, but for me, if the images are greater than 100kb each (or if I'm doing a lot of image retrieval), I'll use the Documents approach.

How to simply store some files

I'm developing an app which needs to show some logos. These logos are just 8kb PNG files, and I'm just going to handle a little amount of them (10-20 at most). However, these are downloaded from the Internet because they might change. So, what I'm trying to achieve is, making the app to download them (done), storing them into the file system, and only downloading again whenever they change (might be months).
Everyone seems to use Core Data, which in my opinion is something designed for bigger and more complex things, because my files will always have the same name plus don't have relations between them.
Is the file system the way to go? Any good tutorial?
Yes, the file system is probably your best option for this. You say that you've already implemented the downloading. How have you done so? With NSURLConnection? If so, then at some point, you have an NSData object. This has a couple of write... methods you can use to save the data to a file on the filesystem. Be sure to save the files in the right place, as your app is sandboxed and you can't write anywhere you like.
The advantage Core Data brings is efficiency. Using NSFetchedResultsController to display your logos in a tableview gets you optimized object loading and memory management. It will automatically load only the items which can be displayed on one screen, and as the user flicks through the table it will handle releasing items which move offscreen. Implementing that on your own is not a simple task.
If you want to build and display your data without Core Data, you'll probably want to use NSKeyValueCoder, which will allow you to easily write an array or dictionary of objects (including nested arrays, dictionaries, and images).

Resources