Создать UICollectionView программно

Я пытаюсь научиться использовать UICollectionView, создавая его программно. Я следил за некоторыми учебными пособиями, чтобы создать образец представления коллекции размером 500 x 500, где каждая ячейка имеет размер 245 x 45. Пока что я могу видеть представление коллекции, но оно не содержит ячеек, и я не знаю, почему. Вот что я сделал:

//подкласс UICollectionViewLayout

@interface LabelCVLayout : UICollectionViewLayout

@property (nonatomic) UIEdgeInsets itemInsets;
@property (nonatomic) CGSize itemSize;
@property (nonatomic) CGFloat interItemSpacingY;
@property (nonatomic) NSInteger numberOfColumns;

@end

@implementation LabelCVLayout

- (id)init 
{
    self = [super init];
    if (self) {
        [self setup];
    }

    return self;
}

- (void)setup
{
    self.itemInsets = UIEdgeInsetsMake(22.0f, 22.0f, 13.0f, 22.0f);
    self.itemSize = CGSizeMake(245.0f, 45.0f);
    self.interItemSpacingY = 12.0f;
    self.numberOfColumns = 3;
}

@end

//контроллер представления, который отображает представление коллекции

@interface TempViewController () <UICollectionViewDataSource, UICollectionViewDelegate>

@property (strong, nonatomic) UICollectionView *collectionView;

@end

@implementation TempViewController


- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1; 
}

- (NSInteger)collectionView:(UICollectionView *)collectionView
 numberOfItemsInSection:(NSInteger)section
{
    return 4;
}

//THE BELOW DELEGATE METHOD DOES NOT GET CALLED!
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView   cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"newCell" forIndexPath:indexPath];

    cell.backgroundColor = [UIColor whiteColor];

    UILabel *testLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, cell.size.width, cell.size.height)];
    testLabel.font = [UIFont fontWithName:ProximaNovaSemibold size:15];
    testLabel.text = [NSString stringWithFormat:@"Label %i", indexPath.row];
    testLabel.clipsToBounds = YES;
    testLabel.backgroundColor = [UIColor clearColor];
    testLabel.textColor = [UIColor blackColor];
    testLabel.textAlignment = NSTextAlignmentLeft;

    [cell addSubview:testLabel];

    NSLog(@"test!"); //does not print!

    return cell;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    LabelCVLayout *flowLayout = [[LabelCVLayout alloc]init];
    self.collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0,0,500,500) collectionViewLayout:flowLayout];
    self.collectionView.backgroundColor = [UIColor redColor];
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;

    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"newCell"];

    [self.view addSubview:self.collectionView];
}

@end

Как ни странно, после установки точек останова я обнаружил, что методы источника данных numberOfSections и numberOfItemsInSection вызываются, а метод cellForItemAtIndexPath НЕ вызывается.

Мне интересно 1) кто-нибудь может увидеть, что я пропустил? и 2) если позже я захочу создать представление коллекции, которое добавляет столько ячеек в строку, сколько будет соответствовать ограничениям размера размера ячейки и размера представления коллекции (т. е. я не хочу определять фиксированное число столбцов), должен ли я создавать подкласс UICollectionViewFlowLayout, а не UICollectionViewLayout?




Ответы (1)


Насколько я вижу, в вашем подклассе UICollectionViewLayout отсутствуют некоторые важные методы. Поскольку это абстрактный класс, согласно документации Apple здесь вам необходимо переопределить следующие методы:

collectionViewContentSize
layoutAttributesForElementsInRect:
layoutAttributesForItemAtIndexPath:
layoutAttributesForSupplementaryViewOfKind:atIndexPath: (if your layout supports supplementary views)
layoutAttributesForDecorationViewOfKind:atIndexPath: (if your layout supports decoration views)
shouldInvalidateLayoutForBoundsChange:

Это, вероятно, объясняет, почему обратный вызов не вызывается. Возможно, вы захотите переключиться на реализованный FlowLayout, хотя бы для его тестирования. Наконец, что касается 2), я не уверен, что вы хотите сделать, но не стал бы

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

из UICollectionViewDelegateFlowLayout сделать свое дело? В зависимости от размера вашей ячейки у вас может быть ряд с 3 ячейками, занимающими почти все пространство, и еще один с 10 маленькими ячейками. Не стесняйтесь уточнить свой вопрос, если это не так.

person Nerkatel    schedule 22.07.2013
comment
Да, я собирался предложить перейти на подкласс UICollectionViewFlowLayout, так как похоже, что он только что после пользовательского макета потока. - person Fogmeister; 22.07.2013
comment
Спасибо! переход на макет UICollectionViewFlow решил проблему, и предложенный вами метод был именно тем, что я искал. - person jac300; 22.07.2013