How to load two images from url in UItableview customcell - ios

In my application I have used custom tableviewcell for loading two images in one cell, my problem is when I am loading that images on my view first time, it show swaped images (1st image in 2nd image and 2nd in 1st) and then after fraction of seconds it loads proper images (1st in 1st and 2nd in 2nd image). I am using AsyncImageView Class for display image.
Every first time view load it shows wrong and then after correct every time.
In CellForRow
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:celllookAlik.btnFullImg.frame];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
imageView.tag = IMAGE_VIEW_TAG1;
[celllookAlik addSubview:imageView];
AsyncImageView *imageViewll = [[AsyncImageView alloc] initWithFrame:celllookAlik.lookAlikeImage.frame];
imageViewll.contentMode = UIViewContentModeScaleAspectFill;
imageViewll.clipsToBounds = YES;
imageViewll.tag = IMAGE_VIEW_TAG2;
[celllookAlik addSubview:imageViewll];
Display Image in cell using below code:
NSString * imageImage = #"";
imageImage = [[self.arrayResponseLookAlike objectAtIndex:indexPath.row] objectForKey:#"ImagePath"];
AsyncImageView *imageViewCelebrity = (AsyncImageView *)[celllookAlik viewWithTag:IMAGE_VIEW_TAG1];
//cancel loading previous image for cell
[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:imageViewCelebrity];
//load the image
imageViewCelebrity.imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#",imageImage]];
NSString * imageImageceleb = #"";
imageImageceleb = [[self.arrayResponseLookAlike objectAtIndex:indexPath.row ] objectForKey:#"LookLikeImage"];
AsyncImageView *imageViewllTemp = (AsyncImageView *)[celllookAlik viewWithTag:IMAGE_VIEW_TAG2];
//cancel loading previous image for cell
[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:imageViewllTemp];
//load the image
imageViewll.imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#",imageImageceleb]];

I have suffered with this type of problem, i have used SDWebImage.frameword.
This framework integration is very easy, and it will load the images properly.
For this first we need to create UIImageView in place of AsyncImageView.
Display Image in cell using below code:
[mMainImgView setImageWithURL:[NSURL URLWithString:loImgurl] placeholderImage:[UIImage imageNamed:#"placeholder"]];
for remaining details check with https://github.com/rs/SDWebImage

Related

SDWebImage - Image from url didn't replace placeholder image after it's finished download

I'm using SDWebImage to download and cache images in an UIImageView asynchronously but I'm facing some problems.
In my project I create a pin marker which has a dialogue box that have UIImageView in it.
The problem that I face is the image from url didn't replace place holder image after it's finished download. The first click on pin marker will always display the place holder image.
The image from url will only display after I click pin marker for the second time.
I want to display image from the url in the first click what should I do?
here is my code
-(UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker{
PlaceData *currentMarker = [self findDataByMarker:marker];
UIView *dialogView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 261, 95)];
// Create background image
UIImageView *dialogBackground = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"MapDialog.png"]];
[dialogView addSubview:dialogBackground];
UIImageView * thumbnail = [[UIImageView alloc] init];
[thumbnail sd_setImageWithURL:[NSURL URLWithString:currentMarker.thumbnail] placeholderImage:[UIImage imageNamed:#"placeholder.png"] options:SDWebImageRefreshCached];
NSLog(#"URL %#", currentMarker.thumbnail);
NSLog(#"thumbnail %#",thumbnail);
CGRect tmpFrame = thumbnail.frame;
tmpFrame.origin.x = 15;
tmpFrame.origin.y = 14;
tmpFrame.size.width = 55;
tmpFrame.size.height = 55;
thumbnail.frame = tmpFrame;
thumbnail.contentMode = UIViewContentModeScaleToFill;
[dialogView addSubview:thumbnail];
return dialogView;
PS. Please help me solve this problem and sorry for my english.
[.retryFailed, .refreshCached] helped solve my issue with this.
imageView.sd_setImage(with: picnicThumbnail, maxImageSize: 100000, placeholderImage: placeholderImage, options: [.retryFailed, .refreshCached], completion : nil)
Please try with this code
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[thumbnail sd_setImageWithURL:[NSURL URLWithString:currentMarker.thumbnail] placeholderImage:[UIImage imageNamed:#"placeholder.png"] options:SDWebImageRefreshCached];
});

Images not release in memory

I have table with Images cell. Images download from internet and save in local disk. Count = 200. Tableview show this images. When scroll content to bottom, comes message memory warning... Used memory 250 - 300 mb O_O!!! Links to images that do not keep.
NSString *cellID = #"cellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
...
NSString* imagePath = [arrayContent objectAtIndex:indexPath.row];
UIImage* image = [[UIImage alloc] initWithContentsOfFile:imagePath];
[cell.imageView setImage:image];
Why hide images not release?
Replace this line
UIImage* image = [[UIImage alloc] initWithContentsOfFile:imagePath];
with this and check once
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
Well I used a custom MSAsyncImageCell class that replaces its image when reused by iOS. It loads the image from a URL asynchronously, displaying a "loading" image gracefully and release memory when reused for another image. If you want I can post the code here but the code is a bit long.
Here is the part of code that actually loads the image. I have images off web/caches so it is NSData.
- (BOOL)_loadImageWithData:(NSData *)imageData
{
UIImage *image = [UIImage imageWithData:imageData];
// Just in case loading failed.
if (image)
{
// Extra check - don't mix up.
if ([[self.currentURL absoluteString] isEqualToString:[self.imageURL absoluteString]])
self.asyncImageView.image = image;
return YES;
}
return NO;
}

How to Display first 9 images in UICollectionview?

I have a image url plist with 50 image urls.Iam trying to display that in a UICollectionview but it getting too slow.Iam displaying 9 cells(images) at a time like 3x3 (3 rows and 3 columns).How can i display first 9 images at loading time and next 9 images on next scrolling .?is that possible? i tried SDWebImages for loading images ,Its not working for me.Please help me.
CODE INSIDE collectionView cellForItemAtIndexPath: ()
the code inside comment take lots of time for loading image,that code is used for loading image from document directory if image is not there then i will display in one place holder image
cell = nil;
cell = (GMMCollectionViewCell *)[self.collectionView dequeueReusableCellWithReuseIdentifier:#"test" forIndexPath:indexPath];
cell.tag = indexPath.row;
docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path;
BOOL isImageLoaded = YES;
/////////////////////PROBLEM CODE:TAKING TOO MUCH TIME TO LOAD IMAGE //////////////////////
bookImage = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#", docPath, [[allbooksImage objectAtIndex:indexPath.row] lastPathComponent]]];
//////////////////////////////////////////////////////////////////////////////////
if(bookImage == nil){
isImageLoaded = NO;
}
if(!isImageLoaded){
[[cell grid_image] setImage:[UIImage imageNamed:#"App-icon-144x144.png"]];
} else{
[[cell grid_image] setImage:bookImage];
}
sharedManager.bookID=bookId;
return cell;
This is what iam expecting
But iam getting like this ,
App Loading time Without any scroll (first image:3 columns are empty)
App screen after first scroll (second image:last column displaying 2 images ,rest of the part still empty )
App screen after a long scroll (third image: last colum some images are there ,rest of the columns still empty)
App screen again scroll to top,so the first image changed
You can try the below code
[[cell grid_image] setImage:nil];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
bookImage = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#", docPath, [[allbooksImage objectAtIndex:indexPath.row] lastPathComponent]]];
dispatch_async(dispatch_get_main_queue(), ^{
if (bookImage)
{
[[cell grid_image] setImage:bookImage];
}
else
{
[[cell grid_image] setImage:[UIImage imageNamed:#"App-icon-144x144.png"]];
}
});
});
hope it will work for you.

Add new image and remove old image from image view

In my ipad app, i has 200 images and i add these images into an array.
Then add this array into image view by looping.
Then, i add this image view as sub view of scroll view.
When i open app, my app is crash.
I try with reducing image size. But, it didn't work.
One of my friend told firstly i should add only image1 and image2.
When user scroll image1, then it show image2.
After that image1 is remove from image view.
And add image3 to image view.
He told it can maintain memory usage.
But, i don't know how can i do that? :D
Please, give me some example.
Thanks in advance.
My code is here,
- (void)viewDidLoad
{
[super loadView];
self.view.backgroundColor = [UIColor grayColor];
UIScrollView *ScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 44, self.view.frame.size.width, self.view.frame.size.height)];
ScrollView.pagingEnabled = YES;
// Create a UIImage to hold Info.png
UIImage *image1 = [UIImage imageNamed:#"Image-001.jpg"];
UIImage *image2 = [UIImage imageNamed:#"Image-002.jpg"];
UIImage *image200 = [UIImage imageNamed:#"Image-200.jpg"];
NSArray *images = [[NSArray alloc] initWithObjects:image1,image2,...,image200,nil];
NSInteger numberOfViews = 200;
for (int i = 0; i < numberOfViews; i++)
{
CGFloat xOrigin = i * self.view.frame.size.width;
UIImageView *ImageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOrigin, 0, self.view.frame.size.width, self.view.frame.size.height-44)];
[ImageView setImage:[images objectAtIndex:i]];
[ScrollView addSubview:ImageView];
}
ScrollView.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);
[self.view addSubview:ScrollView];
It looks like you're accessing the images array at indexes 0..200, but it contains only three elements. Either set numberOfViews = 3;, or index into the array like this:
ImageView.image = images[i%3];
The modulo index will cause you to add each of the three images in a repeating sequence and still let you test with a larger number of scrollView subviews. I doubt that your crash is about memory with only 200 images, unless they are super-huge ones.
You should use a table view to display your images. You don't want to create an array of all those images, because that puts all those images into memory -- not a good thing. You don't even need to create an array to hold the names, since they have names you can easily construct from an integer (which you can get from indexPath.row in the tableView:cellForRowAtIndexPath: method). Something like this:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 200;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *imageName = [NSString stringWithFormat:#"Image-%.3d.jpg",indexPath.row +1];
UIImage *image = [UIImage imageNamed:imageName];
cell.imageView.image = image;
return cell;
}
This example just uses the cell's default imageView to show the images, which is pretty small. You would probably want to create a custom cell with a larger image view in it (or a couple side by side if you want more than one image per row).

Asynchronously load image in uitableviewcell

I am trying to asynchronously load an image in a UITableVIew.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
NSString *cellIndetify = [NSString stringWithFormat:#"cell%d",tableView.tag -TABLEVIEWTAG];
cell = [tableView dequeueReusableCellWithIdentifier:cellIndetify];
IndexPath *_indextPath = [IndexPath initWithRow:indexPath.row withColumn:tableView.tag - TABLEVIEWTAG];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIndetify];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.backgroundColor = [UIColor blackColor];
// here I init cell image view
UIView *cellSub = [self.waterFlowViewDatasource waterFlowView:self cellForRowAtIndexPath:_indextPath];
cellSub.backgroundColor = [UIColor blackColor];
[cell.contentView addSubview:cellSub];
cellSub.tag = CELLSUBVIEWTAG;
}
// fill image info
[self.waterFlowViewDatasource waterFlowView:self fillDataIntoCellSubview:[cell viewWithTag:CELLSUBVIEWTAG] withIndexPath:_indextPath];
CGFloat cellHeight = [self.waterFlowViewDelegate waterFlowView:self heightForRowAtIndexPath:_indextPath];
CGRect cellRect = CGRectMake(0, 0, _cellWidth, cellHeight);
[[cell viewWithTag:CELLSUBVIEWTAG] setFrame:cellRect];
[self.waterFlowViewDatasource waterFlowView:self relayoutCellSubview:[cell viewWithTag:CELLSUBVIEWTAG] withIndexPath:_indextPath];
return cell;
}
in that ImageView class I init:
(id)initWithIdentifier:(NSString *)indentifier
{
if(self = [super initWithIdentifier:indentifier])
{
self.backgroundColor = [UIColor blackColor];
if (!self.imageView) {
_imageView = [[UIImageView alloc] init];
self.imageView.backgroundColor = IMAGEVIEWBG;
[self addSubview:self.imageView];
self.imageView.layer.borderWidth = 1;
self.imageView.layer.borderColor = [[UIColor colorWithRed:0.85 green:0.85 blue:0.85 alpha:1.0] CGColor];
}
......some others controllers
}
-(void)setImageWithURL:(NSURL *)imageUrl{
UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromKey:[imageUrl absoluteString]];
if (cachedImage) {
self.imageView.image = cachedImage;
}else{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:imageUrl delegate:self options:SDWebImageCacheMemoryOnly userInfo:[[NSDictionary alloc] initWithObjectsAndKeys:[imageUrl absoluteString], #"image_url", [NSValue valueWithBytes:&imageSize objCType:#encode(CGSize)], #"image_size", [NSNumber numberWithInt:arrIndex], #"imageview_index", nil]];
_imageView.image = [UIImage imageNamed:#"album_detail_placeholder.png"];
}
.....
.....
- (void)imageDecoder:(SDWebImageDecoder *)decoder didFinishDecodingImage:(UIImage *)image userInfo:(NSDictionary *)userInfo {
imageView.image = image
}
As you see here I used SDWebImageManager, but that doesn't seem to be the problem.
When pull up to next page, before the next page's images have loaded, if I scroll back to previous page's loaded image, the image will be covered by another image (which is should display in the newest page, not current page...) (for example, in the first page, I have a image and there is cat in this image, and then I scroll down till pull up to request next page, and after get all next page image's url, start asynchronous thread download images, before the newest images downloaded, scroll back to top, maybe first page. After awhile, some images downloaded, they should display in there cell, but now the images will cover the current page images, maybe the cat image now have a dog image on it) what shall I do?
When a row is scrolled off-screen, the table view reuses that row's cell for another row that has scrolled on-screen.
The problem is that you are using the ImageView as the delegate of the background loader, and the ImageView is associated with a cell, not a row. By the time the background loader finishes loading the image, the cell may have been reused for another row.
You need to make the table view's data source be the delegate for the background image loader. It should put the index path of the row into the userInfo dictionary when it calls downloadWithURL:delegate:options:userInfo:. When the downloader sends imageDecoder:didFinishDecodingImage:userInfo: to the data source, the data source should get the index path out of the userInfo and use it to ask the table view for the cell currently displaying that row (by sending cellForRowAtIndexPath: to the table view).

Resources