SDImageCache not working - ios

I am encountering a very strange issue in my application.
I have used SDWebImage in the application, to download the images to cache, when network present and then retrieve the images from the cache, when absent.
The SDWebImage works perfectly in case of UITableViews. One can even see the stored/cached image files in the iPhone Simulator folder.
And then theres this one piece of code, that is troubling me.
I am displaying a simple imageview, and caching the image from the network.
The image is displayed properly, when network is present.
But in case of no connectivity, nothing is displayed.
Am assuming, that the caching is not taking place.
Lines of code
dispatch_async(dispatch_get_main_queue(), ^{
[im setImageWithURL:[NSURL URLWithString:[[NSString stringWithFormat:#"%#%#",kImgaePath,[[marrresultingArraySet objectAtIndex:0] objectAtIndex:kIndex_RecipeImage_Local]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[UIImage imageNamed:#"no_imagepng.jpg"]];});

Related

How to cache CollectionViewCell images that is part of custom UITableViewCell

So, I have this news feed structure. Every news block is a custom UITableViewCell. Now, every custom cell has a CollectionView that shows images.
The problem is that when scrolling, and news cell (news block) comes out visible, the CollectionView is reloading - every time cell shows up. I'm trying to find the way to cache those images on the main ViewController side.
What would be the best approach?
If you want to avoid implementing your own cache/disk/memory handlers for this kind of job I strongly recommend either AFNetworking or SDWebImage that handle it all for you.
An example of SDWebImage on how to set an image and its cache:
[imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
This handles all the cache/disk/memory for you automatically.
Here is example of how you handle cache with SDWebImage:
// Set memory size limit (check with older devices to avoid memory errors when setting it to high value.)
[[SDImageCache sharedImageCache] setMaxMemoryCost:****];
// Clear disk cache
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
}];
// Clear memory cache
[[SDImageCache sharedImageCache] clearMemory];
I would stay away from NSUserDefaults or the above mentioned example setting the images to dictionary or arrays to avoid memory errors and app crashes/performance.
You have to cache your UIImage instance, so, if you get some pictures from any source, you might write something like below:
/* some code before */
UIImage *yourImage = /* Get your UIImage from any available way */
[self.cache setObject:yourImage forKey:#"SomeUniqueID"];
/* some code after */
I guess, this code will look greater as a function, which obtains UIImage instance and it's id as parameters.
For my opinion, it's the most common way to store images. If you need a more proficient way without any overheads with third-party frameworks, you can read the documentation about NSCache.
But in general, you have a lot of different ways how to store your images:
Get the image from the disk
Get the image from the memory
Use one of the variants above, but apart them still use some lightweight & flexible frameworks, you can find a lot of on the GitHub.
So, the code I wrote above will just store images into the memory cache.

iOS UITableViewCell Images from URL

I am loading images in my UITableViewCell from some web url and those images are in size around 80-100 kb per image. Everything works fine when i download images asynchronously but when i scroll the tableview, images start again downloading. Can i get rid of this as i have only limited no of rows.
I want if images from url download once should not be download again as it does makes view not comfortable for users when images starts downloading again.
I am using below code to load images in CellforRowAtIndexPath:
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:url];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
cell.eventImage.image= [UIImage imageWithData:data];
});
});
You should use SDWebImage which will cache image on your device and if same image came from server then it load from your local device.
Add SDWebImage to your project.
import <SDWebImage/UIImageView+WebCache.h> header
then add below code at cellForItemAtIndexPath:
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:#"your image URL"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
Better make use of SDWebImageCache for this because this a advantageous third party library to store the image in cache. After downloading once the images will be taken automatically from the cache.
SDWebImageCache
When you Download image put it to the document directory and before you download image check if document directory contains image then load it from there otherwise download from URL
If you want you can make it yourself. You can use NSCache in order to save your images. NSCache it is like NSMutableDictionary (save your image by key). And then you can check it. For key you can use path to your image.
But I also recommend you to use SDWebImage.

SDWebImage not updating image in cache

I am using SDWebImage library for handling image cache. I implemented one of its method to download image from server and populating data in tableView. Here is my code for downloading image and showing in tableViewCell
In cellForRowAtIndexPath, I did the following code
[cell.profileImageView sd_setImageWithURL:[NSURL URLWithString:url] placeholderImage:nil options:SDWebImageRefreshCached];
It works perfectly here. But when I updated image on server, the tableViewCell still shows the same image. The problem is ,its cache is not updating image. I searched with the same keywords and came across this question on StackOverflow. But couldn't resolve the issue. I also tried to clear memory and cache on viewDidDisappear
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:YES];
[[SDImageCache sharedImageCache]clearMemory];
[[SDImageCache sharedImageCache]clearDisk];
}
But its not efficient way. Is there any other way to update the cache when image on server is updated ?
You can use SDWebImageRefreshCached option to refresh concrete image, however you never know if the image was changed on the server side. So it's only your decision should you use image cache or not and when your cache should be updated.
From SDWebImage docs :
If you don't control the image server you're using, you may not be able to change the URL when its content is updated. In such case, you may use the SDWebImageRefreshCached flag. This will slightly degrade the performance but will respect the HTTP caching control headers
[imageView sd_setImageWithURL:url
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageRefreshCached];
It would defeat the purpose of Image Caching if you use this in all your code. Coz the image will be downloaded everytime. Instead you could :
If you manage the server, you could setup some flags in the DB to indicate the image has changed on the server.
Implement some logic to only use SDWebImageRefreshCached once in 2 days or something like that, and use the normal code all other times.
You could also clear the entire cache once in a while to force a refresh, if that's feasible.

How to get the image from in memory cache using SDWebImage?

I have implemented SDWebImage in cellforrowatindexpath method. The problem here is when i scroll down the tableview the images are loading from web which is expected but when i scroll up the tableview the images are again downloading. What is the way to get rid of this problem. I don't want to load images from url overtime (since there is a usage limit with the web service call). I chose to use SDWebImage API for in memory cache so that once the images are loaded they are taken from cache to show it on the UI instead of making the web service call everytime. Here is my code:
[cell.placeImage sd_setImageWithURL:url placeholderImage:nil options:SDWebImageCacheMemoryOnly];
The above line is the only code in that method. Please help me.
Any kind of help is appreciated. I have seen other questions in this community but nobody said how to get an image from the cache memory.
For refreshing of the images you should use option : SDWebImageRefreshCached
[imageView sd_setImageWithURL:url placeholderImage:nil options:SDWebImageRefreshCached];

Use SDWebImage to download two images at once

I'm looking into using SDWebImage to download images into my app. I would like to show an image as quickly as possible, so I have two versions of each image on my server; one low quality and one high quality. Currently, I achieve this by using two NSURLRequest, one for each version of the image. This works perfectly as the app will download both versions simultaneously, show the low quality, then change the image to the high quality version when it's finished downloading.
I tried to replicate this by using:
[imageView setImageWithURL:lowURL];
[imageView setImageWithURL:highURL];
But when I run the app, the second call cancels the first one. Any help with this would be greatly appriciated.
Thanks
modify framework is not a good way to solve problem, unless there is no other better way.
in SDWebImage's UIImageView+WebCache.h category, there are methods for this situation.
eg:
__weak UIImageView *weakImageView = imageView;
[imageView setImageWithURL:thumbURL placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
[weakImageView setImageWithURL:bigURL placeholderImage:image];
}];
If you look into the - (void)setImageWithURL:(NSURL *)url in the UIImageView+WebCache.m file, you will find there is [self cancelCurrentImageLoad]; in the first line, which is cancel the current image loading operation. if you want to load both simultaneously, you can try to comment out this line to test whether it will work as you expected, if cannot then you'd better try other methods.
probably this issue is better being solved in a different way, try pre-fetching the image even before displaying it
this is the swift code to do so
let prefetcher = SDWebImagePrefetcher.shared()
let urls :[URL] = [URL(string: imageStringUrl)]
prefetcher.prefetchURLs(urls)

Resources