HOW to delay loading of images in uicollectionview using objective c - objective-c

In my UICollectionView i am showing images i want to show the images one after another but its coming all at a time though i have used dispatch_after but its not working
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell"forIndexPath:indexPath];
UIImageView *showcardCollectionImageView;
showcardCollectionImageView = [[UIImageView alloc]initWithFrame:CGRectMake(1, 1, cell.frame.size.width - 2, cell.frame.size.height - 2)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSString *cardImageString = [cardsimagearray objectAtIndex:indexPath.row];
showcardCollectionImageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.png",cardImageString]];
showcardCollectionImageView.hidden = NO;
[cell addSubview:showcardCollectionImageView];
});
return cell;
}

You can use https://github.com/rs/SDWebImage, it's fast downloading image from server.
#import "UIImageView+WebCache.h"
[imgOffer sd_setImageWithURL:[NSURL URLWithString:objRecord.imgPath]
placeholderImage:[UIImage imageNamed:#""]
options:0]

Related

Objective-C: Self-Sizing Table View Cells with dynamic image's height after download

I wanna resize imageview'height after download image,but some wrong happened as first cell image when first load tableview;
then if I scroll table to make the cell be in visible again,it go to be normal as second image;
I don't known the size of image,can't get from server,how to fix it?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ShopingTableCell* cell = [tableView dequeueReusableCellWithIdentifier:#"shopingCell" forIndexPath:indexPath];
StoreDynamicsModel *model = storeArray[indexPath.row];
cell.contentLabel.text = model.name;
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:model.goods_img_url] placeholderImage:[UIImage imageNamed:#"defaultShort"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
dispatch_async(dispatch_get_main_queue(), ^{
cell.imgViewHeightConstraint.constant = image.size.height * ScreenWidth / image.size.width;
});
}];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 120.f;
return self.tableView.rowHeight;
}
You can set content mode of UIImageView to Aspect Fit.
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
For ref:
How to manage UIImageView content mode?

Show video in collection view cell

I want to show multiple videos in a collection view. I have this code:
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return array.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
NSURL *videoURL = [NSURL fileURLWithPath:#"Path"];
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
AVPlayerViewController *playerViewController = [AVPlayerViewController new];
playerViewController.player = player;
playerViewController.showsPlaybackControls = NO;
playerViewController.videoGravity = AVLayerVideoGravityResizeAspectFill;
playerViewController.view.frame = CGRectMake(0, 0, 200, 200);
[cell insertSubview:playerViewController.view atIndex:0];
[player play];
return cell;
}
But the code is very slowly and the scrolling is not smooth. Can you help me?
Yes, I have sample code that does exactly what you want, and more. You can download the code and see a video showing what it does from/at:
http://demonicactivity.blogspot.com/2016/08/draft-what-in-hell-this-demoniac-is-up.html

Loading url image array add to UIcollectionview

I want to load images array from Url and add to UICollectionView
Tony.pageImages =imagearray;
[Tony reloadData];
NSLog(#"imagearray%#",imagearray);
Tony is Collection view.h/m files. pageImages is NSMutableArray on the Tony.h files. The Image array display console log mean i got image array correctly
Those are Url.
but when i add code on the UICollectionView method it doesn't work
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
UIImageView *CollectionViewImage = (UIImageView *)[cell viewWithTag:120];
CollectionViewImage.image= [UIImage imageNamed:self.pageImages[indexPath.row]];
return cell;
}
Do i miss something ?
This is my imagearray
imagearray = [[NSMutableArray alloc]init];
for (int i = 0;i < comment.count; i++)
{
[imagearray addObject:comment[i][#"pic_url"]] ;
}
You have to implement and set the following dataSource delegate UICollectionViewDataSource in your viewcontroller:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section {
return imagearray.count;
}
If I got it right, you need to load image from URL.
To do that simply add this code:
[CollectionViewImage.image setImageWithURL:[NSURL URLWithString:self.pageImages[indexPath.row]] placeholderImage:nil];
Or if you want to add placeholder image, just set placeholderImage:[UIImage imageNamed:#"someImageInYourAssets"];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:self.pageImages[indexPath.row]]];
UIImage *image = [UIImage imageWithData: imageData];
CollectionViewImage.image = image;
This is solution how solve problem loading image from url,without addition frameworks such as "Heneke","AFNetworking"..etc..In Objective C Image View can't communicated with URL directly, but can using NSData as Helper Object(wrapper).

UICollectionViewCell willAppear not being called

I'm trying to do a UICollectionView of articles that doesn't eats RAM like an elephant. So, the UICollectionView consists of full screen cells that contain one image. If the UICollectionViewCell appears, the content gets loaded in. This is the code:
- (void)viewDidLoad {
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 0;
_collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
[_collectionView setDataSource:self];
[_collectionView setDelegate:self];
_collectionView.pagingEnabled = YES;
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[_collectionView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:_collectionView];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
//add UIImageView here
//add UITextView with tag 123 here
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [_collectionView cellForItemAtIndexPath:indexPath];
UITextView *textView = [cell viewWithTag:123];
textView.text = #"Testing this out.";
}
However, this doesn't do anything. No errors are thrown, it just doesn't do anything. What am I doing wrong?

How to show an UIActivityindicator in UICollectionview customcell untill the image downloads at server side?

Can Any one help me how to show the activity indicator until the image for UICollection cell downloads at back end.
In my code the activity indicator is show only for last cell..Don't know where I m making the mistake
Here is my code:
- (collectionCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{
[self.menuCollectionView registerNib:[UINib nibWithNibName:#"collectionCell"
bundle:nil] forCellWithReuseIdentifier:#"CELL"];
collectionCell= [menuCollectionView dequeueReusableCellWithReuseIdentifier:#"CELL"
forIndexPath:indexPath];
MenuItems *item=[itemsfinal objectAtIndex:indexPath.row];
NSMutableString *str = [NSMutableString stringWithFormat:#"%#", item.itemImage];
NSLog(#" url %#",str);
UIImage *image = [UIImage imageWithContentsOfFile:[self loadImage:str]];
if(image !=nil){
collectionCell.menuRecipeImage.image = image;
collectionCell.activityIndicator.hidden = YES;
[collectionCell.activityIndicator stopAnimating];
}else{
collectionCell.activityIndicator.hidden = NO;
[collectionCell.activityIndicator startAnimating];
collectionCell.menuRecipeImage.image = [UIImage imageNamed:#"menudefualt.png"];
}
return collectionCell;
}
In cellForItemAtIndexPath you should set up your activity indicator. Then start loading your image for the cell in the background. When the image have loaded apply it to the cell on the main thread.
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
__block UICollectionViewCell* cell = [cv dequeueReusableCellWithReuseIdentifier:#"cell"
forIndexPath: indexPath];
// Placeholder text --
UILabel* label = [[UILabel alloc] initWithFrame:cell.bounds];
label.text = #"Downloading...";
[cell.contentView addSubview:label];
// Load image in background --
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSURL* url = [NSURL URLWithString: [NSString stringWithFormat:#"http://example.com/img/img%02lu.png", (long unsigned)indexPath.row]];
// Load and decode image --
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
// Apply image on the main thread --
dispatch_sync(dispatch_get_main_queue(), ^{
UIImageView* iv = [[UIImageView alloc] initWithImage:image];
[cell.contentView addSubview:iv];
});
});
return cell;
}
The example in action...
One thing about Niels example is that this may cause an incorrect image to be set for a cell, if the cell is re-used before the image is completely loaded (eg. if you're scrolling quickly). So you need to keep a map of what URL should be set for each cell, so roughly modifying Niels' example above:
#property NSDictionary *cellMap;
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
__block UICollectionViewCell* cell = [cv dequeueReusableCellWithReuseIdentifier:#"cell"
forIndexPath: indexPath];
// Placeholder text --
UILabel* label = [[UILabel alloc] initWithFrame:cell.bounds];
label.text = #"Downloading...";
[cell.contentView addSubview:label];
NSURL* url = [NSURL URLWithString: [NSString stringWithFormat:#"http://example.com/img/img%02lu.png", (long unsigned)indexPath.row]];
[cellMap setObject:url forKey:cell];
// Load image in background --
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Load and decode image --
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
// Apply image on the main thread --
dispatch_sync(dispatch_get_main_queue(), ^{
NSURL *cellUrl = [cellMap objectForKey:cell];
if (cellUrl == url) {
// Only set the image if the url is still the same for this cell
UIImageView* iv = [[UIImageView alloc] initWithImage:image];
[cell.contentView addSubview:iv];
}
});
});
return cell;
}
You should use async image load. It can be done with GCD
//First start your activityIndicator
collectionCell.activityIndicator.hidden = NO;
[collectionCell.activityIndicator startAnimating];
//Then using GCD load your image on secondary thread
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//Here your image loading from url
UIImage *image = [UIImage imageWithContentsOfFile:[self loadImage:str]];
dispatch_async(dispatch_get_main_queue(), ^{
//This block (Main thread) waits until your image will be downloaded
//(Note that all operation with views must be executed on a main thread)
//Then loading is done just set your image and stop activityIndicator
collectionCell.menuRecipeImage.image = image;
collectionCell.activityIndicator.hidden = YES;
[collectionCell.activityIndicator stopAnimating];
});
});
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section{
return _items.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
ImageFilterCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ImageFilterCell" forIndexPath:indexPath];
cell.lblEffectName.text = [_itemsName objectAtIndex:indexPath.row];
cell.imgLoader.hidden = NO;
cell.imgFilter.image = nil;
NSString *effectName = _items[indexPath.row];
if([effectName isEqualToString:#"Original"]){
cell.imgLoader.hidden = YES;
cell.imgFilter.image = _imgThumb;
}
else {
UIImage *filteredImage = [_filteredImages objectForKey:effectName];
if(filteredImage){
cell.imgLoader.hidden = YES;
cell.imgFilter.image = filteredImage;
} else {
__weak ImageFilterCell *weakCell = cell;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self getFilteredImageForEffect:effectName forImage:_imgThumb completionBlock:^(UIImage *image) {
dispatch_async(dispatch_get_main_queue(), ^{
weakCell.imgLoader.hidden = YES;
weakCell.imgFilter.image = image;
[_filteredImages setObject:image forKey:effectName];
});
}];
});
}
}
if(_checkedIndexPath==indexPath.row)
cell.highlighted = YES;
else
cell.highlighted = NO;
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if(_checkedIndexPath != indexPath.row && indexPath.row!=0){
_checkedIndexPath = indexPath.row;
NSString *effectName = _items[indexPath.row];
if([_delegate respondsToSelector:#selector(showIndicator)]){
[_delegate showIndicator];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self getFilteredImageForEffect:effectName forImage:_orgImage completionBlock:^(UIImage *image) {
dispatch_async(dispatch_get_main_queue(), ^{
if([self.delegate respondsToSelector:#selector(filterImageView:filteredImage:)]){
[self.delegate filterImageView:self filteredImage:image];
}
});
}];
});
} else if (indexPath.row == 0) {
_checkedIndexPath = 0;
if([self.delegate respondsToSelector:#selector(filterImageView:filteredImage:)]){
[self.delegate filterImageView:self filteredImage:_orgImage];
}
}
[_collectionView reloadData];
}