Shmidt
Shmidt

Reputation: 16664

UICollectionViewCell imageView

Code works fine until I changed UIViewController with tableView to UICollectionViewController.

Now all cells shows same image, sometimes it flipping to nil. However textLabels are OK.

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TourGridCell";
    TourGridCell *cell = (TourGridCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
    Guide *guideRecord = [self.fetchedResultsController objectAtIndexPath:indexPath];

    cell.titleLabel.text = [guideRecord.name uppercaseString];

    cell.titleLabel.backgroundColor = [UIColor clearColor];
    if ([guideRecord.sights count] > 0) {

        if ([[guideRecord.sights objectAtIndex:0]valueForKey:@"thumbnail"]) {
            cell.imageView.image = [UIImage drawImage:[[guideRecord.sights objectAtIndex:0]valueForKey:@"thumbnail"] inImage:[UIImage imageNamed:@"MultiplePhotos"] inRect:CGRectMake(11, 11, 63, 63)];

        }else {
            cell.imageView.image = [UIImage imageNamed:@"placeholder2"];
        }

        NSMutableString *sightsSummary = [NSMutableString stringWithCapacity:[guideRecord.sights count]];
        for (Sight *sight in guideRecord.sights) {
            if ([sight.name length]) {
                if ([sightsSummary length]) {
                    [sightsSummary appendString:@", "];
                }
                [sightsSummary appendString:sight.name];

            }
        }
        if ([sightsSummary length]) {
            [sightsSummary appendString:@"."];
        }
        cell.sightsTextLabel.text = sightsSummary;
        cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(@"%i", nil) , [guideRecord.sights count]];
        cell.detailTextLabel.hidden = NO;
        //        cell.textLabel.alpha = 0.7;
        NSPredicate *enabledSightPredicate = [NSPredicate predicateWithFormat:@"notify == YES"];
        NSArray *sightsEnabled = [[[guideRecord.sights array] filteredArrayUsingPredicate:enabledSightPredicate]mutableCopy];
        NSPredicate *visitedSightPredicate = [NSPredicate predicateWithFormat:@"visited == YES"];
        NSArray *sightsVisited = [[[guideRecord.sights array] filteredArrayUsingPredicate:visitedSightPredicate]mutableCopy];

        if ([sightsEnabled count] > 0)
        {
            NSLog(@"green_badge");
            cell.notifyIV.image = [UIImage imageNamed:@"green_badge"];
        }
        else if (sightsVisited.count == 0) {
            NSLog(@"new_badge");
            cell.notifyIV.image = [UIImage imageNamed:@"new_badge"];
        }
        else
        {
            cell.notifyIV.image = nil;
        }

    }
    else {
        cell.notifyIV.hidden = YES;
        //        cell.textLabel.textColor = RGB(0, 50, 140);
        cell.detailTextLabel.hidden = YES;
        cell.sightsTextLabel.text = nil;
    }

    return cell;
}

Cell set up in storyboard,

//  TourGridCell.h
#import <UIKit/UIKit.h>

@interface TourGridCell : UICollectionViewCell
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIImageView *notifyIV;
@property (weak, nonatomic) IBOutlet UILabel *textLabel;
@property (weak, nonatomic) IBOutlet UILabel *detailTextLabel;
@property (weak, nonatomic) IBOutlet UILabel *sightsTextLabel;

@end


#import "TourGridCell.h"

@implementation TourGridCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end

Upvotes: 0

Views: 7979

Answers (3)

So Over It
So Over It

Reputation: 3698

if you are doing custom drawing in your cell, you will need to inform the cell to 'redraw' itself when a cell has been 'reused'. This is perhaps easiest done by implementing the prepareForReuse method in your UICollectionViewCell subclass.

- (void)prepareForReuse {
    [super prepareForReuse];
    [self setNeedsDisplay];
}

Technically, we probably don't need to include [super prepareForReuse] as the documentation suggests 'The default implementation of this method does nothing'. However, it is good practice, and who knows if Apple will change the default implementation of prepareForReuse in the future.

Upvotes: 1

Shmidt
Shmidt

Reputation: 16664

Solution is to nullify image each time in cellForItemAtIndexPath:

cell.imageView.image = nil;

Upvotes: 1

TheBasicMind
TheBasicMind

Reputation: 3585

you may need to provide some more data for it to be possible for others to work out what the problem is. I take it you have checked that at the different times this is called the conditions are being triggered so different images are actually being instantiated and added to your UICollectionViewCell? Also I take it you are aware a UICollectionViewCell doesn't have an image property so you will need to add a property in it's subclass (if you want easy access to the view without the overhead of retrieving it using it's tag ID) and ensure the view is added as a subview ?

I think, given the symptoms you have described, such a problem can occur if you are not adding your sub-views to the UICollectionViewCell's contentView. Apple's collection views have all manner of optimisations to ensure high performance and only the subviews of the UICollectionViewCell's content view (which is itself a sub-view of UICollectionViewCell) will be consistently drawn as you expect.

Though based on what you have provided, I can't be definitive as to if this is the cause of the problem.

@implementation UICollectionViewCellSubView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        _imageView = [[UIImageView alloc] initWithFrame:frame];
        [self.contentView addSubview:_imageView];
    }
    return self;
}


- (void)prepareForReuse
{
    [super prepareForReuse];
    // ensure you do appropriate things
    // here for when the cells are recycled
    // ...

}   

@end

Upvotes: 2

Related Questions