2015-07-27 5 views
1

Я новичок в UICollection View. Некоторые ячейки не отображаются, как показано на изображении ниже. Это мой код для его настройки, был бы счастлив, если бы кто-нибудь мог объяснить, почему некоторые ячейки отсутствуют. Кроме того, при прокрутке вверх и вниз изображения в ячейке будут меняться по какой-либо причине (хотя на этом снимке экрана я использую одни и те же изображения для всех ячеек). Вся вторая и четвертая строки отсутствуют, а средний столбец отсутствует. Цель состоит в том, чтобы иметь ряды по три изображения на одну строку рядом друг с другом. Благодаря!UICollectionView неправильно отображает ячейки

UICollectionViewFlowLayout *layout=[UICollectionViewFlowLayout new]; 
    self.collectionView=[[UICollectionView alloc] initWithFrame:Frame(0,225,1080, Denormalize(screenHeight) - 225) collectionViewLayout:layout]; 
    [self.collectionView setDataSource:self]; 
    [self.collectionView setDelegate:self]; 

    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"]; 
    [self.collectionView setBackgroundColor:[UIColor redColor]]; 
    layout.minimumLineSpacing = 0; 
    layout.minimumInteritemSpacing = 0; 
    layout.sectionInset = UIEdgeInsetsMake(0,0,0,0); 

    [self.view addSubview:_collectionView]; 

#pragma mark - CollectionView delegate 
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
{ 
    return self.allVideos.count; 
} 

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath: 
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath]; 
// cell.backgroundColor=[UIColor greenColor]; 

    NSDictionary *video = self.allVideos[indexPath.row]; 

    UIImageView *thumbnail = [UIImageView new]; 
    thumbnail.contentMode = UIViewContentModeScaleAspectFill; 
    thumbnail.frame = cell.frame; 
    thumbnail.clipsToBounds = YES; 
    thumbnail.image = [UIImage imageNamed:@"DefaultAvatar.png"]; 
// thumbnail.image = video[@"image"]; 
    [cell addSubview:thumbnail]; 

    return cell; 
} 

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return CGSizeMake(self.view.frame.size.width/3, self.view.frame.size.width/3); 
} 

enter image description here

ответ

3

Одной из основных проблем является то, что вы добавляете UIImageView как подвид в cellForItemAtIndexPath. Этот метод запускается каждый раз, когда ячейка удаляется, а не каждый раз, когда инициализируется ячейка. Это означает, что каждый раз, когда одна из этих ячеек отображается так, как при прокрутке коллекции, новое подвью добавляется поверх существующего изображения в ячейке. Это очень быстро вызовет серьезные проблемы на графике и использует больше памяти, чем вы намереваетесь. Первое, что я хотел бы сделать, это подкласс UICollectionViewCell и добавить ваш UIImageView в подкласс. Затем вы можете установить образ ячейки в этом методе, но добавление subview в этом конкретном месте - действительно плохая идея.

Вот мой подход.

Во-первых, сделайте подкласс ячейки и выставьте способ установки изображения.

// MyCollectionViewCell.h

#import <UIKit/UIKit.h> 

@interface MyCollectionViewCell : UICollectionViewCell 

- (void)setImage:(UIImage *)image; 

@end 

// MyCollectionViewCell.m

#import "MyCollectionViewCell.h" 

@interface MyCollectionViewCell() 

@property (strong, nonatomic) UIImageView *imageView; 

@end 

@implementation MyCollectionViewCell 

-(instancetype)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     [self setupImageView]; 
    } 
    return self; 
} 

- (void)setupImageView 
{ 
    UIImageView *imageView = [[UIImageView alloc]init]; 
    imageView.backgroundColor = [UIColor greenColor]; 
    [self addSubview:imageView]; 
    self.imageView = imageView; 

    [imageView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
    NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]; 
    NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0]; 
    NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; 
    NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; 

    [self addConstraints:@[leading, trailing, top, bottom]]; 

} 

- (void)setImage:(UIImage *)image 
{ 
    [self.imageView setImage:image]; 
} 

@end 

Формуляр ограничение здесь являются ключевыми. UICollectionViewCells, по моему опыту, часто имеют фрейм 0, когда они инициализируются, поэтому вы видите тонну пустых ящиков (UIImageView в новой ячейке инициализируется CGRectZero). Ограничения будут гарантировать, что когда они в конечном итоге выйдут правильно, imageView также изменит размер, чтобы соответствовать.

После этого, зарегистрировать свой собственный класс клеток, а затем вы можете реализовать это в CollectionViewController

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
    MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 
    [cell setImage:[UIImage imageNamed:@"emoji.jpg"]]; 
    // Configure the cell 

    return cell; 
} 

Вот до и после выстрелов установки UIImageViewFrame явно

layout with frame on initWithFrame:

vs. используя NSLayoutConstraints.

layout with constraints

Для ада этого, вот, как сделать то же самое в cellForItemAtIndexPath.

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 

    NSInteger viewTag = 1000; 
    UIImageView *imageView = (UIImageView *)[cell viewWithTag:viewTag]; 

    if (!imageView) { 
     imageView = [[UIImageView alloc]init]; 
     imageView.tag = viewTag; 
     [cell addSubview:imageView]; 

     [imageView setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]; 
     NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0]; 
     NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; 
     NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; 
     [cell addConstraints:@[leading, trailing, top, bottom]]; 
    } 

    imageView.image = [UIImage imageNamed:@"emoji.jpg"]; 

    return cell; 
} 
+0

Хороший вопрос, хотя он не затрагивает вопрос. Я ненавижу подклассирование - делает код слишком зернистым. Есть ли способ проверить, есть ли у клетки уже дерьмо? – etayluz

+0

Я обновил свой комментарий, включая мое исправление недостающих изображений, используя ограничения макета. Вы могли бы гипотетически пометить подзаголовок, который вы добавляете в cellForItemAtIndexPath, а затем проверить подпункты ячейки для представления с вашим конкретным тегом, но для этого потребовалось бы итерации над подзонами ячеек всякий раз, когда он удаляется, что является дополнительной работой без реальной причины.Я думаю, что стандартная и предпочтительная практика в объектно-ориентированных языках, таких как Obj-C, определенно будет подклассом в этом случае. – Dare

+0

Yup, это было бы принятым способом - ну, я встроенный парень C - объектно-ориентированный никогда не был моим делом, мне нравится код, короткий, читаемый, сладкий и лаконичный. Если у вас есть идея, почему UICollectionView пропускает некоторые ячейки, дайте мне знать, возможно, есть способ проверить, была ли ячейка уже инициализирована для этой строки, прежде чем вызывать dequeueReusableCellWithReuseIdentifier – etayluz

Смежные вопросы