I am using SDWebImage library in order to download and cache images and from a web service asynchronously. Following is the method i use to download the images:
- (void) downloadThumbnails:(NSURL *)finalUrl
{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:finalUrl
options:0
progress:nil
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
{
if (image)
{
[self setThumbnail:image];
}
}];
}
It is successfully downloading the images from the web service and showing them in the tableview. However its not persisting the images between application runs. Is there anything else i need to do in order to cache the images??
UPDATE: KINDLY DO NOT suggest to use the following:
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
Because, the structure of my program is different. Secondly, if you read description of the SDWebImage library HERE, you will get to know that it can be used the way i am using it using SDWebImageManager.
I suspect that the reason why the cache mechanism in SDWebImage is not working correctly in this specific case is because it is based on the image URL.
So, if you just download an image and assign it to some of your object's property (like you are doing assigning it to thumbnail), if you later access that property if will simply walk around the cache mechanism.
What you could do to keep the structure of your program is:
store the thumbnailURL in your self object;
when you download the image the first time, call SDWebImageManager downloadWithURL: method as you are doing; this will also store the image in the cache; (this you are already doing as per your code above)
make thumbnail a read-only property that accesses the cache retrieving the image associated to thumbnailURL.
This is the least amount of changes you should do.
This could be an implementation of the read-only property described at point 3:
- (UIImage*)thumbnail {
return [[SDImageCache sharedCache] imageFromDiskCacheForKey:self.thumbnailURL];
}
where self.thumbnailURL is another property in your object where you save the image URL.
Hope this helps.
I think you are on wrong path.
If you want to use SDWebImage for UITableView Than Do Following.
1.import UIImageView+WebCache.h by following statement where u have UITableView
#import <SDWebImage/UIImageView+WebCache.h>
2.Write following line in cellForRowAtIndexPath method Of UITableView
[cell.Logo setImageWithURL: finalUrl placeholderImage:[UIImage imageNamed:#"imagename.png"] options:SDWebImageRefreshCached];
Replace LOGO with name of your image view in UITableViewCell
imagename.png is name of image in project which will display till image not load from internet.
Comment here if u face any problem.
All the best
i prefer the following method for asynchronous image downloading in tableview.
Actually, you don't need to handle SDWebImageManager yourself.
[cell.imageView setImageWithURL:[NSURL URLWithString:#"IMAGE_URL"]];
[cell.imageView setImageWithURL:[NSURL URLWithString:#"IMAGE_URL"] placeholderImage:[UIImage imageNamed:#"LOCAL_IMAGE_NAME"]];
Make sure you imported the UIImageView+WebCache.h in your implementation.
The same above asynchronous image loading is also available for UIButton+WebCache.h category and MKAnnotationView+WebCache.m category.
The new version of SDWebImage also supports the GIF animation using UIImage+GIF.h category
https://github.com/rs/SDWebImage
Related
SDWebImage is an extension to UIImageView. There is a method:
sd_setImageWithURL(NSURL(string: url), placeholderImage: placeholder, options: options, completed: { image, error, cache, url in
//do sth after it is completed
})
But in completed block I cannot decide whether to allow SDWebImage assign the image or not. It is assigned automaticaly without asking developer about permission to do this. The problem arise when I assign the image to UIImageView within UITableViewCell while scrolling the table.
It is obvious that before it finishes downloading, that cell may be reused for different row, and finally there may be a different image.
How to fix it using this library?
In following question: Async image loading from url inside a UITableView cell - image changes to wrong image while scrolling, there is an answer that SDWebImage solve this problem, but it is not true, or I missed sth.
This shouldn't be necessary. If you look inside the implementation of the UIImageView category you will see this:
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
[self sd_cancelCurrentImageLoad];
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
What this shows you is that the minute you call setImage it cancels the download associated with the image view instance. Since UITableView reuses its views this should not be an issue. See how they associate the imageView and URL together.
Your issue is probably the fact that you are not resetting your imageView's image property to nil everytime. So inside cellForRow you probably want:
cell.imageView.image = nil
cell.imageView.sd_setImageWithURL(...)
When you start a new load the image view cancels any current load. So, if the image view is reused this problem is avoided.
If you don't have a new image to set for some reason then you can call sd_cancelCurrentImageLoad and explicitly set your placeholder image.
I want to display an image using a URL in an image view. I tried using this:
[cell.avatarImageView.image setImageWithURL:[NSURL URLWithString:#"http://www.innovaworks.com/wp-content/themes/innovaworks/images/home_person.png"]];
but it gives me this warning :
UIImage may not respond to "setImageWithUrl"
and the image not shown.
There is no method on UIImage to set the image with a url.
See this answer for a full description of how to set an image from the data contents of a url:https://stackoverflow.com/a/2782491/209867
The gist is:
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.innovaworks.com/wp-content/themes/innovaworks/images/home_person.png"]]];
Understand that this is synchronous The scroll performance within a UITableView will be horrendous, and you should not use this! I only provide this answer for technical accuracy and comprehensiveness.
As it looks like you copied this code from somewhere, there are many open source categories that will asynchronously load images from a url.
One such open source project is SDWebImage. https://github.com/rs/SDWebImage It's a widely used project that easily allows you to asynchronously load a UIImage from a url.
-setImageWithURL: is not an UIImage method. You want to fetch the image data first, using NSURLRequest, NSURLSession, etc. (documentation). Then allocate an UIImage and use the initWithData: constructor. Then use the image view's setImage: method to set it.
Try
[cell.avatarImageView setImageWithURL:[NSURL URLWithString:#"http://www.innovaworks.com/wp-content/themes/innovaworks/images/home_person.png"]];
Or
cell.avatarImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.innovaworks.com/wp-content/themes/innovaworks/images/home_person.png"]]];
In my application,I am allowing user to select one or multiple images from gallery and as the user is selecting the images,I am storing all the url in an array
- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
for (NSDictionary *dict in info) {
url = dict[#"UIImagePickerControllerReferenceURL"];
[self.images addObject:url];
NSLog(#"array value:%#",self.images);
[self.myPDTable reloadData];
}
}
The output I get is
array value:(
"assets-library://asset/asset.JPG?id=74236046-12DA-4E75-9038-A3092D31005B&ext=JPG",
"assets-library://asset/asset.JPG?id=98FC160A-60E1-4F29-80C8-1AED036F1140&ext=JPG",
"assets-library://asset/asset.JPG?id=4D18448E-9796-47AE-A534-FB3E64518B89&ext=JPG",
"assets-library://asset/asset.JPG?id=38099BA1-4988-46CB-ADE9-E1F3F896147A&ext=JPG",
"assets-library://asset/asset.JPG?id=86556040-16C6-47BB-8CBA-F5164771EC9F&ext=JPG"
)
Now my problem is that I don't know how to use these value and display them in my table view cell.
What you've got in each element of your array is an asset URL. To get from an asset URL to an image, start with the ALAssetsLibrary object, call assetForURL:resultBlock:failureBlock: to fetch the corresponding asset (the photo file), and, in the resultBlock, pull out the thumbnail and use it in your interface.
Here's some typical code for getting from an ALAsset to a usable image:
ALAsset* photo = // let's assume you've obtain an asset
CGImageRef im = photo.aspectRatioThumbnail;
UIImage* im = [UIImage imageWithCGImage:im scale:0
orientation:UIImageOrientationUp];
However, you've made a very odd design choice here. assetForURL:resultBlock:failureBlock: is time-consuming and operates asynchronously; it is not suitable for calling in a table view data source method (when you configure your cells), which needs to be fast. In didFinishPickingMediaWithInfo:, why did you ask the info for its UIImagePickerControllerReferenceURL? You don't need an array of URLs; you need an array of images! The info was offering you the image right then (its UIImagePickerControllerOriginalImage); why didn't you take it when it was offered? You could have just grabbed the image, sized it down, and stuck the sized-down image into your table data model, ready for use.
(Also, it is silly and wasteful to call reloadData every time through the for loop. You should call it just once, after you've gathered all the images into your model.)
I saw two different methods for downloading image from URL:
[imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeHolderImage"]];
and
AFImageRequestOperation *requestOperation = [AFImageRequestOperation imageRequestOperationWithRequest:...
Which one should I use ?
It depends on what you want to achieve.
The first method is built around UIImageView (as a category) and allows to download and display images as they are. Usually this method can be useful in table views or other similar interfaces that contains UIImageViews. First you will see (if set) a placeholder. When the image is completely downloaded, the placeholder, will be replaced with the real image.
The second method, instead, is useful if you need to download an image and perform some processing. Using completion block, you can verify when the image has been downloaded and do scale, etc.
The most important thing is that while the first method performs an association with the image view and the relative image, in the second case you need to do it your own. Anyway, the second is more flexible since you have a direct control over the image and, so, perform, additional calculations.
Hope it helps.
[imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeHolderImage"]];
i use this one in my project and its work fine for me.
I want to put an image preview on my table cells which derives from the RSS item that they load when pushed to.
I'm not sure what UIImage method to use for cell.imageView.image....
Right now it's got...
imageWithContentsOfFile
, which doesn't crash, but also doesn't display anything because....
I also want to know how best to derive the image data from the block of html, being that I'm using an open source parser (should I try to nab it in there, or create my own class for deriving it from the description string that the parser created?
I much prefer to try to create my own solutions rather than fill my project with a hundred open source library files.
Thank you for your thoughts...
UIImage* myImage = [UIImage imageWithData:
[NSData dataWithContentsOfURL: [NSURL URLWithString: #"http://example.com/image.jpg"]];
cell.imageView.image = myImage;