【问题标题】:UICollectionView: custom FlowLayout crash if empty sectionsUICollectionView:如果为空部分,则自定义 FlowLayout 崩溃
【发布时间】:2016-08-17 11:09:06
【问题描述】:

我在使用自定义流布局时遇到问题,如果我的部分为空,我会收到 "EXC_ARTHMETIC(code=EXC_I386_DIV, subcode=0x0)"

我正在使用自定义 FlowLayout 添加自定义标题和自定义部分背景(崩溃与背景有关)。
一些代码(请查看layoutAttributesForBackgroundAtSection: 了解崩溃发生的位置):

//  UIViewController 

   -(void)loadView
   {
    [super loadView];

    collectionViewFlowLayout *flowLayout = [[collectionViewFlowLayout alloc]init];
    flowLayout.sectionInset = UIEdgeInsetsMake(35, 20, 0, 20);
    [flowLayout setItemSize:cellSize];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
    flowLayout.minimumInteritemSpacing = 0.0f;

    self.collectionView = [[UICollectionView alloc]initWithFrame:(CGRectZero) collectionViewLayout:flowLayout];
    [self.collectionView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.collectionView setBackgroundColor:[UIColor colorWithRed:246./256. green:246./256. blue:246./256. alpha:1]];
    [self.view addSubview:self.collectionView];

    [[self.collectionView.topAnchor constraintEqualToAnchor:self.view.topAnchor] setActive:YES];
    [[self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] setActive:YES];
    [[self.collectionView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor] setActive:YES];
    [[self.collectionView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor] setActive:YES];

    [self.collectionView registerClass:[collectionViewCell class] forCellWithReuseIdentifier:reuseCellIdentifier];
    [self.collectionView registerClass:[sectionHeaderReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:reuseHeaderIdentifier];
    [self.collectionView registerClass:[sectionBackgroundReusableView class]
            forSupplementaryViewOfKind:KindSectionBackground
                   withReuseIdentifier:NSStringFromClass([sectionBackgroundReusableView class])];

    [self.collectionView setShowsHorizontalScrollIndicator:NO];
    [self.collectionView setShowsVerticalScrollIndicator:YES];

    [self.collectionView setDataSource:self];
    [self.collectionView setDelegate:self];
   }



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

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


-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionV
           viewForSupplementaryElementOfKind:(NSString *)kind
                                 atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableview = nil;

    if (kind == UICollectionElementKindSectionHeader)
    {
        reusableview = [collectionV dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:reuseHeaderIdentifier forIndexPath:indexPath];
        NSString *sectionName = self.shelves[indexPath.section];

        [(sectionHeaderReusableView*)reusableview configureWithTitle:sectionName];
    }
    if (kind == UICollectionElementKindSectionFooter)
    {

    }
    if (kind == KindSectionBackground)
    {
        reusableview = [collectionView dequeueReusableSupplementaryViewOfKind:sectionBackground
                                                          withReuseIdentifier:NSStringFromClass([sectionBackgroundReusableView class])
                                                                 forIndexPath:indexPath];
    }
    return reusableview;
}

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    return = KHeaderSize;
}

// FloawLayout 子类

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray *attributes = [NSMutableArray arrayWithArray:[super layoutAttributesForElementsInRect:rect]];

    // 1. get visible sections
    NSInteger lastIndex = -1;
    for(UICollectionViewLayoutAttributes * attr in attributes) {
        lastIndex = attr.indexPath.section;
        UICollectionViewLayoutAttributes * attr = [self layoutAttributesForBackgroundAtSection:lastIndex];
        [attributes addObject:attr];
    }

    return attributes;
}

-(UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind
                                                                     atIndexPath:(NSIndexPath *)indexPath
{
    if([kind isEqualToString:KindSectionBackground]) {
        return [self layoutAttributesForBackgroundAtSection:indexPath.section];
    } else {
        return [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
    }
}

-(UICollectionViewLayoutAttributes *)layoutAttributesForBackgroundAtSection:(NSUInteger)section
{
    NSIndexPath * indexPath =[NSIndexPath indexPathForItem:0
                                                 inSection:section];
    UICollectionViewLayoutAttributes * attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:KindSectionBackground
                                                                                                             withIndexPath:indexPath];
    attr.hidden = NO;
    attr.zIndex = -1;


  // crash happen in the line below.
  UICollectionViewLayoutAttributes * firstAttr =   [selflayoutAttributesForItemAtIndexPath:indexPath];


    CGRect frame;
    frame.origin.x = firstAttr.frame.origin.x - self.sectionInset.left;
    frame.origin.y = firstAttr.frame.origin.y - self.sectionInset.top;

    frame.size.width = self.collectionView.bounds.size.width;

    NSUInteger numItems = [self.collectionView numberOfItemsInSection:section];

    CGFloat cellsPerLine = floorf(self.collectionView.bounds.size.width / self.itemSize.width);
    NSUInteger numLines = ceilf(numItems / (float)cellsPerLine);

    frame.size.height = numLines * firstAttr.size.height + (numLines-1)*self.minimumLineSpacing +
    self.sectionInset.top + self.sectionInset.bottom;

    attr.frame = frame;

    return attr;
}

请您帮忙解决一下,谢谢。

【问题讨论】:

    标签: ios uicollectionview flowlayout


    【解决方案1】:

    当 IndexPath 中提供的部分为空时,layoutAttributesForItemAtIndexPath 似乎会崩溃。这可能是一个错误,因为它应该返回一个可选的(至少在 swift 中)。我遇到了同样的问题,并通过检查该部分中的项目数量来解决它(第 1 部分的快速示例):

    if dataSource.collectionView(collectionView, numberOfItemsInSection: 1) > 0 {    
        if let layoutAttributes = self.layoutAttributesForItem(at: IndexPath(row: 0, section: 1)) {
            // update layoutAttributes or create your background attributes
        }
    }
    

    【讨论】:

      【解决方案2】:

      一种解决方法是在调用任何布局方法之前提前调用collectionView.reloadData(),这对我有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-29
        • 1970-01-01
        • 2021-05-14
        • 1970-01-01
        • 1970-01-01
        • 2019-06-15
        相关资源
        最近更新 更多