Pregunta UICollectionView simple para mostrar imágenes se comporta de forma extraña: algunas imágenes se muestran correctas, algunas en la posición incorrecta, algunas faltan en absoluto


Quiero mostrar imágenes en una cuadrícula en iPhone usando UICollectionView, mostrando 3 imágenes por fila. Para una "prueba simple muerta" (como pensé), agregué 15 imágenes JPG a mi proyecto, para que estén en mi paquete y pueda cargarlas simplemente a través de [UIImage imageNamed: ...].

Creo que he hecho todo lo correcto (configuración y registro de la subclase UICollectionViewCell, uso de los métodos del protocolo UICollectionViewDataSource), sin embargo, el UICollectionView se comporta de manera muy extraña:

Muestra solo algunas de las imágenes en el siguiente patrón: La primera línea muestra las imágenes 1 y 3, la segunda línea está en blanco, la siguiente línea como la primera (las imágenes 1 y 3 se muestran correctamente), la cuarta línea en blanco, y así sucesivamente ...

Si presiono un botón en mi NavBar que activa [self.collectionView reloadData], aparecen o desaparecen celdas aleatorias. Lo que me vuelve loco es que no es solo un problema de imágenes aparecen o no. En algún momento, las imágenes también se intercambian entre las celdas, es decir, aparecen para un indexPath ¡definitivamente no están conectadas!

Aquí está mi código para la celda:

@interface AlbumCoverCell : UICollectionViewCell
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@end

@implementation AlbumCoverCell
@synthesize imageView = _imageView;
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _imageView = [[UIImageView alloc] initWithFrame:frame];
        [self.contentView addSubview:_imageView];
    }
    return self;
}

- (void)dealloc
{
    [_imageView release];
    [super dealloc];
}

- (void)prepareForReuse
{
    [super prepareForReuse];
    self.imageView.image = nil;
}
@end

Parte del código para mi subclase UICollectionViewController, donde 'imageNames' es un NSArray que contiene todos los nombres de archivo jpg:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.collectionView registerClass:[AlbumCoverCell class] forCellWithReuseIdentifier:kAlbumCellID];
}

#pragma mark - UICollectionViewDataSource Protocol methods
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return [self.imageNames count];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    AlbumCoverCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kAlbumCellID forIndexPath:indexPath];
    NSString *imageName = [self.imageNames objectAtIndex:indexPath.row];
    NSLog(@"CV setting image for row %d from file in bundle with name '%@'", indexPath.row, imageName);
    cell.imageView.image = [UIImage imageNamed:imageName];

    return cell;
}

#pragma mark - UICollectionViewDelegateFlowLayout Protocol methods
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
{
    return CGSizeMake(100, 100);
}

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
{
    return UIEdgeInsetsMake(0, 0, 0, 0);
}

De la declaración NSLog en cellForItemAtIndexPath: puedo ver que se llama al método para todas las celdas (no solo la que se muestra) y que la asignación entre indexPath.row y filename es correcta.

¿Alguien tiene una idea de qué podría causar este extraño comportamiento?


17
2017-12-06 01:11


origen


Respuestas:


Mientras tanto, he encontrado la solución. En realidad, fue un error muy sutil en la implementación de mi UICollectionViewCell subclase AlbumCoverCell.

El problema es que he establecido el marco de la instancia de celda como el marco de la UIImageView subvista en lugar de pasar los límites de la propiedad de la celda contentView!

Aquí está la solución:

@implementation AlbumCoverCell
@synthesize imageView = _imageView;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // WRONG:
        // _imageView = [[UIImageView alloc] initWithFrame:frame];

        // RIGHT:
        _imageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
        [self.contentView addSubview:_imageView];
    }
    return self;
}


- (void)prepareForReuse
{
    [super prepareForReuse];

    // reset image property of imageView for reuse
    self.imageView.image = nil;

    // update frame position of subviews
    self.imageView.frame = self.contentView.bounds;
}

...

@end

50
2018-01-21 12:41