UICollectionView's cellForItemAtIndexPath not

2019-06-12 07:31发布

问题:

I am having an issue adding labels to individual cells in a UICollectionView. Using the code shown bellow, the label is added only to the first cell in the collection and none of the others. However, if I change cell.contentView in the third to last line to collectionView, the labels are all added to the right locations, which means I'm dealing with at least the right frame, but I need the labels to be added to the cells themselves.

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
    UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CalendarItem"
                                                                                                      forIndexPath:indexPath];
    UILabel* dayLabel = [[UILabel alloc] initWithFrame:cell.frame];
    [dayLabel setFont:[UIFont fontWithName:@"Helvetica-Bold" size:15]];
    [dayLabel setBackgroundColor:[UIColor clearColor]];
    [dayLabel setTextAlignment:NSTextAlignmentCenter];
    [dayLabel setText:@"!"];

    [cell.contentView addSubview:dayLabel];
    [cell setBackgroundColor:[UIColor whiteColor]];

    return cell;
}

I'm doing this all programmatically so here is my initialization code for the collection I'm using:

frame.origin.y = self.view.frame.origin.y + ROW_SIZE;
frame.size.height = self.view.frame.size.height/2 - 2 * ROW_SIZE;
UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];   
CGSize size = CGSizeMake(frame.size.width/7 - 2 * CALENDAR_EDGE_SPACING,
                                 frame.size.height/5 - 2 * CALENDAR_EDGE_SPACING);
[flow setItemSize:size];
[flow setScrollDirection:UICollectionViewScrollDirectionVertical];
calendarView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:flow];

[calendarView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"CalendarItem"];

回答1:

You should never be referencing the cell's frame. The collection view moves them around, removes them and generally does unexpected things with cells that you don't want to have to think about.

If you want your label to take up the entire cell you want to set the label's frame to the cell's contentView's frame. Everything should start working perfectly if you do that.

The reason using collectionView works in place of cell.contentView is because, in reality, the cell is at some arbitrary position within the collection view, say (150, 1024). So when you add a label to the content view at origin (150, 1024), it's actually way below the view that you're looking at; but when you add the label directly to the collection view it's at the same position as the cell.