So I am using SDWebImage to load images into the cells.
I want to preload images of the next few cells so that when the user scrolls, the image is already loaded.
Whats the ideal way to do this.
Current code -->
[cell.BGImage sd_setImageWithURL:[NSURL URLWithString:section.imageURL] placeholderImage:[UIImage imageNamed:#"PlaceholderF"]];
Ensuring that the current displayed image is kept at priority loading.
Any suggestions?
You can use SDWebImageDownloader method to download image before your cell load or in other controller. So it will cache image and when your cell load it will show immediately.
[[SDWebImageDownloader sharedDownloader]downloadImageWithURL:nil options:SDWebImageDownloaderContinueInBackground progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
}];
and you can set download image priority in LIFO manner using below code.
[[SDWebImageManager sharedManager].imageDownloader setExecutionOrder:SDWebImageDownloaderLIFOExecutionOrder];
Maybe this will help you.
Related
I need to make a Pinterest style newsfeed. I have created a collection view with 2 columns. I am downloading the photos async in cellForItemAtIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath:(NSIndexPath*)indexPath {
TFNewsObject *obj = [self.sortedDataSource objectAtIndex:indexPath.row];
[imageView sd_setImageWithURL:url placeholderImage:nil options:SDWebImageRefreshCached
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
obj.tfImage = image;
}];
return cell;
}
The problem is that I need to set the size of the cell in heightForItemAtIndexPath and there the image has not been downloaded yet because it did not enter cellForItemAtIndexPath yet. I am setting a fixed size of 100 for the height.
I need to somehow trigger heightForItemAtIndexPath after I've downloaded the image in cellforItemAtIndexPath.
Another thing that I've tried is downloading the image in heightForItemAtIndexPath synchronous and calculating the height after the image downloaded. In that manner it displays correctly with each cell with a different height depending on the image, but it takes forever to load all the images.
Is there a way to modify the cell's height after I've downloaded the image? Thanks!
Try this
[imageView sd_setImageWithURL:url placeholderImage:nil options:SDWebImageRefreshCached
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
obj.tfImage = image;
collectionView .reloadItems(at: [indexPath])
}];
In -setImageWithURLRequest:..., when the image loads it in a hash table so you should then call -reloadItemsAtIndexPaths: with the current image path. This will reload the cell and thus cause the CollectionView to check what size the cell should be.
Another solution that you can try is to invalidate the collection view layout when the image is downloaded.
- (UICollectionViewCell *)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath:(NSIndexPath*)indexPath {
TFNewsObject *obj = [self.sortedDataSource objectAtIndex:indexPath.row];
[imageView sd_setImageWithURL:url placeholderImage:nil options:SDWebImageRefreshCached
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[self.collectionView.collectionViewLayout invalidateLayout];
}];
return cell;
}
After this return a appropriate size in the delegate method:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return /* size */;
}
I got into similar problem while i developed something similar to pinterest layout.
Even we had a lag while downloading images asynchronously and once the download is done refreshing cell by cell will blow away the user and will lead to UI jerks.
The solution which i could suggest is,
For example when the post is created with the image, Calculate the size (width and height) of the image and save it in the DB. So the size of the image is available before the image is downloaded or cached and we could scale the cell to the height of the image and display a default image and when the actual image is cached or downloaded it would silently replace the default image without any UI jerks.
If you are using services like cloudinary then you can avoid the pain of storing the image size (height and width). The cloudinary api will give you the height and width of the image.
I have a dynamic tableview that can be searched through with a search box, and if I load an image in a cell in the background and the search text changes, the object in the cell may also change, and sometimes an old image that was loading in the background will finish and display when it shouldn't. Not every image is loaded in the same way, but this is the method that causes the problem:
[self.CarImage sd_setImageWithURL:imageURL
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageurl){
[self.CarImage setAlpha:0.0];
[UIImageView animateWithDuration:.5 animations:^{
[self.CarImage setAlpha:1.0];
}];
}];
Any ideas would be appreciated
You need to do two things here
1) in prepareforresue method Cancel current downloading request
2) in prepareforresue method set image to nil
Hope this will fix your issue
Here the issue is, image is loaded from url after you have already reused the cell. You can store the url of the image, each and everytime the cell being reused the url of the images should be stored inside the custom cell class. Then inside the completion block check that the loaded image url and the stored image url are same or not using isEqual: method of NSURL. If they are same then everything is ok, cell is not being reused, otherwise the cell is been used for another row, then just dont set the image.
self.carImgUrl = imageURL;//here carImgUrl is a property which you gonna set everytime when the cell is being reused.
[self.CarImage sd_setImageWithURL:imageURL
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageurl){
if([imageurl isEqual:self.carImgUrl])
{
[self.CarImage setAlpha:0.0];
[UIImageView animateWithDuration:.5 animations:^{
[self.CarImage setAlpha:1.0];
}];
}
}];
When I used the method load image, after the image gets downloaded, it does not show until I select or scroll the cell, but if I don't set the placeholderImage to nil, it works well. I don't know what's wrong with. Here's my code:
[cell.imageView sd_setImageWithURL:(my url) placeholderImage:nil];
Some problems with SDWebImage
It's weird, but you can try [cell setNeedsLayout]; after you set the image to reload all the cell views.
I guess you have all the calls inside tableView:cellForRowAtIndexPath:
use completion block to change the image view.
[myImage sd_setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:IMG_PLACEHOLDER] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {}];
use this in your project and try.
Maybe you can use another method to do this, as an example:
[_theImageView sd_setImageWithURL:[NSURL URLWithString:_imageUrl]]
I have a collection view, which contains cells in each section, and each cell has an image in it.
Possibly, the collection view holds 20 or more cells.
I want to load the images off the internet into the cells. The issue is that this can take a few seconds, and I want the collectionView to be displayed even if the images have not downloaded completely.
The collection view is given an array that contains the URLs, and so far, I have been downloading off the internet within collection view cellforitematindexpath
However, the view only becomes visible after all the cells have been loaded, and since each call to collection view cellforitematindexpath downloads an image, if 20 images are pulled off of URLs, it takes way to long.
What can I do to display the view, and THEN download the images, and then display them?
Hope I made myself understandable, if not, please ask!
Thanks!
C
Yes, you could use SDWebImage (as mention at comment above).
Another interesting side you could face out, that if image haven't load yet and user scroll view, it could be problems with dequeueReusableCellWithReuseIdentifier:forIndexPath, so it's better to download images throw id <SDWebImageOperation>.
Prepare for reuse will be something like this:
- (void)prepareForReuse
{
[super prepareForReuse];
if (self.imageOperation)
[self.imageOperation cancel];
self.imageOperation = nil;
}
And load will be like this:
SDWebImageManager *manager = [SDWebImageManager sharedManager];
self.imageOperation = [manager downloadWithURL:[NSURL URLWithString:urlString]
options:SDWebImageRetryFailed
progress:nil
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) {
if (image)
{
self.imageView.image = image;
}
}];
I'm using the following code to lazy load an image into my UIImageView:
[self.imv1 setImageWithURL:[NSURL URLWithString:myURL]
placeholderImage:[UIImage imageNamed:#"loading.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
{
// stuff here
}];
When a user touches a button, I want the lazy loading of this to STOP completely, so that no image gets loaded and the download of the image stops.
After I stop the lazy loading, I plan to load a different image into the same UIImageView.
Is this possible with SDWebImage?
Found out how to do it. I just needed to call this:
[self.imv1 cancelCurrentImageLoad];