I am downloading some images from parse to a UICollectionView. The problem is that the cells are being reused before the images are downloaded. How can I cancel the request and avoid repeating the same images on different cells?
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
WallImage *wallImageFromUser = [DataStore instance].wallImagesFromUser[indexPath.row];
static NSString *identifier = #"Cell";
UserPhotoCollectionViewCell *cell = (UserPhotoCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
if ([[DataStore instance].wallImagesFromUser count] > 0) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void){
UIImage *postedImage = [UIImage imageWithData:[wallImageFromUser.imageFile getData]];
dispatch_async(dispatch_get_main_queue(), ^(void){
[cell.userPhotoButton setImage:postedImage forState:UIControlStateNormal];
});
});
}
return cell;
}
I have tried to use [wallImagesFromUser.imageFile cancel] but with no success.
Any suggestions?
According to me you should create your cell identifier name as your customcell name. it is better approach to avoid repeating of cell in your app. and try to this
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"UserPhotoCollectionViewCell";
UserPhotoCollectionViewCell *cell = (UserPhotoCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void){
WallImage *wallImageFromUser = [DataStore instance].wallImagesFromUser[indexPath.row];
UIImage *postedImage = [UIImage imageWithData:[wallImageFromUser.imageFile getData]];
dispatch_async(dispatch_get_main_queue(), ^(void){
[cell.userPhotoButton setImage:postedImage forState:UIControlStateNormal];
});
});
return cell;
}
but i prefer SDWebImage to download image in cell of collectionview/tableview
you can use SDWebImage third party to download image in your collectionview cell's image. it download image once and set image to that particular cell. it reduce the problem of repeating image in collectionview cell. it improve your app performance also. you can download here
https://github.com/rs/SDWebImage
Related
I have a sample app of StudentRecord in which i have a UICollectionview of student's images. I want to add button to last cell and this button should add student's image to the last cell.
Following is my existing code, how to modify it-
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *myCell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"MyCell"
forIndexPath:indexPath];
UIImage *image;
long row = [indexPath row];
image = [UIImage imageNamed:studentImages[row]];
myCell.imageView.image = image;
return myCell;
}
I have a UICollectionView which shows a list of playlists and an image from one of the songs in the playlist.
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
playlistCell* cell = [cv dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
if(!cell)
{
cell = [[playlistCell alloc] init];
}
// Configure the cell...
MPMediaItem *rowItem = [[playlists objectAtIndex:indexPath.row] representativeItem];
UIImage *cellBG = [self getAlbumArtworkWithSize:CGSizeMake(320, 320) forPlaylist:[playlists objectAtIndex:indexPath.item]];
cell.image = cellBG;
return cell;
}
However, it jerks/stutters when I scroll. It's not smooth at all and can be a pain to scroll through.
How would I make this smoother?
You can make the UI more responsive simply by loading your images in the background with GCD like this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
playlistCell * cell = [cv dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
if(!cell)
{
cell = [[playlistCell alloc] init];
}
// Configure the cell...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
MPMediaItem *rowItem = [[playlists objectAtIndex:indexPath.row] representativeItem];
UIImage *cellBG = [self getAlbumArtworkWithSize:CGSizeMake(320, 320) forPlaylist:[playlists objectAtIndex:indexPath.item]];
dispatch_async(dispatch_get_main_queue(), ^{
cell.image = cellBG;
});
});
return cell;
}
I have an UICollectionView with images, now I want to add a sticker to all images from 5th image to the end. I use the following code, and It works, but when I scroll down to the end, then scroll it back, all stickers appears on ALL IMAGES.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.layer.borderWidth = 0.3;
recipeImageView.layer.borderColor = [UIColor blackColor].CGColor;
recipeImageView.image = [UIImage imageNamed:[wallPack objectAtIndex:indexPath.row]];
// add Paid stickers
NSString *stickName = [NSString stringWithFormat:#"stickerImage.png"]; /// image name
UIImage *stickImage = [UIImage imageNamed:stickName];
stickView = [[UIImageView alloc] initWithImage:stickImage];
stickView.contentMode = UIViewContentModeScaleAspectFit;
if (indexPath.row >= 5) {
[recipeImageView addSubview:stickView];
}
return cell;
}
where is the problem? why before scrolling down everything appears as I want, from 5th to the end, but when I scroll it back, the sticker image puts on ALL images.
The cells are reused. You must add the sticker to the ones you want to add it to if it is not there, but also remove it from the ones where you don't want want it if it is there.
I would suggest creating UICollectionViewCell subclass wherein you can add a property for stickImage and set it (based on your condition).
Moreover in prepareForReuse function you can default it to whatever you want, it will also make your
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
a bit more cleaner.
i have try to create a simple photo browser, and i used UICollectionView, when i try to insert them thumb images to the cell, it does't work,it has a thread, but i can't fixed it,please help me, thank you very very much. here is my code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ImageCell";
ImageCell *cell = (ImageCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
NSArray *images = #[#"http://www.example.com/p1.jpg",#"http://www.example.com/p2.jpg",#"http://www.example.com/p3.jpg",#"http://www.example.com/p4.jpg"];
cell.imageView.image = [UIImage imageNamed:images[indexPath.row]];
return cell;
}
You can also use SDWEBIMAGE. thus you can use
[cell.imageView setImageWithURL:[NSURL URLWithString:#"Your image url"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
see this link.
I need to display around 300 images on UICollectionView. I have added custom UICollectionViewCell and subview UIImageView, now when i try to display images on UICollectionView from web server it display around 150 images and then app crashes showing low level memory. Below is my code, please let me know what i am doing wrong.
-(void)updateView {
for (int i = 0; i < m_nPhotoCount; i ++)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *imageURL = [NSURL URLWithString:[aryList objectAtIndex:i]];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];
if(image == nil)
{
NSLog(#"kashif");
}
else {
[self.imageArray addObject:image];
}
dispatch_sync(dispatch_get_main_queue(), ^{
[collectionView reloadData];
});
});
}
}
#pragma mark - UICollectionView Datasource
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
return [self.imageArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"GalleryCell";
GalleryCell *cell = (GalleryCell*)[cv dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
cell.imageView.image = [self.imageArray objectAtIndex:indexPath.row];
return cell;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
return [[UICollectionReusableView alloc] init];
}
You are taking up the wrong approach. What you should do is, You should download only those number of images (equivalent to number of visible cells of CollectionView) at once.
When collection view is scrolled than download more images and purge or store previous images in the cache.
You can make use of this wonderful Image Downloading and caching library : SDWebImage
There are special libraries available for gallery. You should try library rather handling or creating collection view with large size.