Which image caching library for iOS? - iphone

I am building a photo album app and find a few image caching libraries, namely:
JMImageCache
HJCache
SDWebImage
What one you'd recommend (or other libs not on the list)? I am looking for:
Efficiency
Minimum effort in terms of garbage collection
Support for Blocks preferred
Thanks

Personally, I think SDWebImage is the best because it is an absolute no-effort solution, and provides the simplest mechanism for cache handling as it is simply an extension of the UIImageView class.

Image async downloading and caching is not a simple task. It needs to be done well otherwise it will defeat its purpose. Therefore I strongly suggest that eventually you build your own. Having said that, I needed a quick and simple solution in order to move forward with the development of my application.
I found these solutions:
HJCache
SDWebImage
Apple's LazyTableImages
An adaption from Apple's LazyTableImages,MHLazyTableImages
I tried HJCache, but it didn't offer great scrolling performance when handling large images (1.5M+). For small images it worked great though. Tried both LazyTableImages as well but the integration wasn't simple.
Ultimately, I chose SDWebImage. The integration couldn't be simpler. Once you have linked the library to your project all you need to do is:
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
in your tableView:cellForRowAtIndexPath:.
Additionally:
Works with custom cells as well
Doesn't block the UI
Offers great scrolling performance
Image downloading and caching is seamless.

There are multiple frameworks that solve this problem. Just to name a few:
Swift:
Nuke (mine)
Kingfisher
AlamofireImage
HanekeSwift
Objective-C:
AFNetworking
PINRemoteImage
YYWebImage
SDWebImage

Try also APSmartStorage. It automatically caches UIImage/NSData on disk or in memory.
It has cute Blocks–style API;
// setup data parsing block
APSmartStorage.sharedInstance.parsingBlock = ^(NSData *data, NSURL *url)
{
return [UIImage imageWithData:data scale:UIScreen.mainScreen.scale];
};
...
// show some progress/activity
...
// load object with URL
[APSmartStorage.sharedInstance loadObjectWithURL:imageURL callback:(id object, NSError *error)
{
// hide progress/activity
if (error)
{
// show error
}
else
{
// do something with object
}
}];
It's quite smart and still simple:

I tried using SDWebImage.
Agreed that it is very easy to integrate.
However the big issue with this library is that it does not honour "max-age" cache control.
The library is still under development but they are not picking this limitation.

I strongly recommend you to try Kingfisher and SDWebImage. Both works perfectly for downloading and caching images from the web.

Moa
Moa is an image download library written in Swift. It allows to download and show an image in an image view by setting its moa.url property.
Installation
Use CocoaPods to add Moa to your project. Just add the following line to your Podfile.
pod 'moa', '~> 8.0'

Related

How can I speed up the loading of images from a web service?

I'm new to iPhone development. In my application, I had kept a scrollview and I have loaded the images from web service using JSON parsing. Unfortunately, it is taking too much time to load them. Do you have any suggestions on how to speed up the (down)loading?
Well there can be many routes you can take to make image loading faster but the one thing I would recommend most is utilize AFNetworking's "UIImageView+AFNetworking" category which you can find here:
http://afnetworking.com/
It loads images quickly and doesnt tie up the main thread. If you have a preloader image you want to display while it is downloading you can do that as well.
AND it's really easy:
[imageView setImageWithURL:[NSURL URLWithString:#"…"]];

How to use SDWebImage without any cache for one instance

I use the SDWebImage image downloading/caching library pretty much any time I display an image in a table view.
I would usually implement it like so (in a table view cellForRowAtIndexPath method).
[cell.imageView setImageWithURL:
[NSURL URLWithString:#"http://asite.com/animage.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
And that would load a cached version if it had one.
What about if I wanted to use the simplicity of SDWebImage (with the placeholder / robust downloading code) - but without the cache in just one place.
I know how to disable caching throughout SDWebImage, but I don't know how you would call setImageWithUrl: placeholderImage: making sure that SDWebImage doesn't use any cache?
The reason I want to do this is I'm using it to display webcams in a table view (obviously, you want this updated every time).
I recommend moving away from the Category on UIImageView and creating your own version of SDWebImageManager. You'd get more control if you use the class SDImageCache yourself.
Heres and example right from SDWebImageManager itself:
[[SDImageCache sharedImageCache] storeImage:image
imageData:downloader.imageData
forKey:[downloader.url absoluteString]
toDisk:NO];
toDisk is probably where I changed the BOOL to NO, the default manager uses disk caching. You may also want to clear the memory every so often to support your streaming images:
[[SDImageCache sharedImageCache] clearMemory];
The SDWebImageManager code is easy to follow and I imagine you won't need to reinvent most of it, just a few important portions to suit your needs.
Here you go. Make sure you get the latest version of SDWebImage:
[anImageView setImageWithURL:[NSURL URLWithString:#"http://asite.com/animage.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageCacheMemoryOnly];
From SDWebImageManager.h:
/**
* This flag disables on-disk caching
*/
SDWebImageCacheMemoryOnly = 1 << 2,
Swift 4.2
Xcode: 10.0
SDWebImage: ~>4.0
SDImageCache.shared().config.shouldCacheImagesInMemory = false
You just need to use the shouldCacheImagesInMemory property from SDImageCache and set it to NO.
This feature available in 3.7.4+.
You can use SDWebImageDownloader. It doesn't cache data.
You should use SDWebImageManager.shared.loadImage with fromLoaderOnly option

WebP image format on iOS

I’m currently researching the possibility to use Google’s WebP image format in our iOS software.
I found it’s not hard to decode the WebP into RGBA8888 as needed using the Google’s C-library.
However, I’d like to create an implementation comparable to UIImage in terms of both API and performance.
Q1. Is it possible in iOS to develop an image decoder so that native imageWithData and other APIs will read the new format?
Q2. If no, what API does UIImageView (and other framework-provided controls) use to draw the UIImage? Is it public (e.g. drawInRect/drawAtPoint) or internal?
Can I inherit from UIImage, override a few methods (such as +imageWithContentsOfFile, +imageWithData, +imageNamed, -drawInRect, -drawAtPoint), and have my WPImage objects behave well with SDK-provided APIs?
Q3. If every instance of my hypothetical WPImage class will subscribe for UIApplicationDidReceiveMemoryWarningNotification (to flush RGBA image buffer leaving the much smaller original WebP data in RAM), won’t it hurt the performance much?
The software we’re developing may easily have hundreds of different images in RAM.
I made full (decode/encode) UIImage wrapper for WebP.
https://github.com/shmidt/WebP-UIImage
There is an example . https://github.com/carsonmcdonald/WebP-iOS-example
WebP Image Support Coming to iOS 14
update your devices.
Another example I've written uses the work that Carson McDonald started but in a reusable fashion. Basically you add the WebP.framework to your project (included in my example or create-able using the instructions Carson has on his website) and then you can do something like this:
#import "UIImage+WebP.h"
...
self.imageView.image = [UIImage imageFromWebP:#"path/to/image.webp"];
// or
[self.button setImage:[UIImage imageFromWebP:#"path/to/image.webp"
forState:UIControlStateNormal]];
If you want to take a look at my example, go here: https://github.com/nyteshade/iOSWebPWithAlphaExample
First, decode the WebP pixels into a buffer. You then need to call CGDataProviderCreateWithData() to create a "data provider" for CoreGraphics and then call CGImageCreate() and pass in the provider and all the needed arguments. Finally, invoke UIImage imageWithCGImage:imageRef in order to create a UIImage instance.
SDWebImage is a library which provides an async image downloader which can easily be extended to support WebP via SDWebImageWebPCoder.

lazyload images on the iphone

Does anyone know of a good tutorial that shows how to lazy load images in a UITableView? I've searched online but the only one I found that looked like it did what I wanted was hard to follow because only parts of the code were shown and I'm new at this so I didn't understand how to hook everything up.
I suggest you check out the SDWebImage project on github, I use it for my table views when I need to load a remote image into the cells.
https://github.com/rs/SDWebImage
As Daniel suggested SDWebImage https://github.com/rs/SDWebImage, I don't know of any tutorial, but in amongst the KTPhotoBrowser samples there is one that uses SDWebImage that can show you how to do it https://github.com/kirbyt/KTPhotoBrowser/tree/master/src/Sample/Classes/SDWebImageSample
If I remember correctly you need to import and use the SDWebImage UIImageView category and then pass the url to the cell and call
setImageWithURL:[NSURL URLWithString:#"yoururl"] placeholderImage:[UIImage imageNamed:#"placeholder.png"]
when setting the cell image.
I haven't actually followed it, but this one has plenty of positive commentary: http://www.markj.net/iphone-asynchronous-table-image/

asynchronous image loader in UITableView

Does anyone know any good library/tutorial that can do asynchronous image loading for a cell in UITableView? I am looking for a method that doesn't involve too much code changing in my current code and easy to integrate to a regular synchronous UITableView.
Try looking into Three20
An open source library written by the guy who wrote the official "Facebook" app for iOS.
Moreover, the code of the facebook app is based on that library.
If you rather do it by yourself, read MHLazyTableImages, it comes with a github project. It's an adaptation of Apple's LazyTableImages. Or you can use HJCache.
Fully-Loaded is another one which is pretty simple. It's more a generic image view loaded which you can use in custom table view cells.
https://github.com/foursquare/fully-loaded
I quite like SDWebImage, which is an asynchronous image downloader with cache support with an UIImageView category.
https://github.com/brendanlim/SDWebImage