- iPhone系统
iOS 9.2 iOS 9.3.5 (12.0系统未出现崩溃)
- 布局情况
一个collectionView中有5个section,第一个section的header与其余的header不同,并且只有最后一个section有footer,其他section没有footer。
- 崩溃操作
当后台返回数据中,只给出了一个section的数据,其余四个section没有数据。即:只显示第一个section的header和items。
此时发生崩溃,崩溃在返回header 和 footer的数据源方法处,报出断言失败 。
*** Assertion failure in -[ShopInfoCollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:]
或者
*** Assertion failure in -[UICollectionViewData layoutAttributesForSupplementaryElementOfKind:atIndexPath:]
// 初始化方法中注册 item header footer
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout*)layout
{
self = [super initWithFrame:frame collectionViewLayout:layout];
if(self) {
[self registerClass:[CollectionCell class] forCellWithReuseIdentifier:@"cell"];
[self registerClass:[CollectionHeader_1 class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeader_1"];
[self registerClass:[CollectionHeader_2 class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeader_2"];
[self registerClass:[CollectionFooter class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"CollectionFooter"];
}
return self;
}
// 返回item的size
- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath*)indexPath{
return CGSizeMake((375 - 30)*0.5, (375 - 30)*0.5*1.5);
}
// 返回header的size
- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
if(section ==0){
return CGSizeMake(375, 100);
}else{
return CGSizeMake(375, 70);
}
}
// 返回footer的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{
if (section == _sourceArr.count - 1){
return CGSizeMake(375, 50);
}else{
return CGSizeZero;
}
}
// 返回 item
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionCell *item = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
return item;
}
// 返回header 和 footer
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == 0){
// *****************崩溃在这个位置*********************
CollectionHeader_1 *header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeader_1" forIndexPath:indexPath];
return header;
}else if (indexPath.section == _sourceArr.count - 1){
if (kind == UICollectionElementKindSectionHeader){
CollectionHeader_2 *header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeader_2" forIndexPath:indexPath];
return header;
}else{
CollectionFooter *footer = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"CollectionFooter" forIndexPath:indexPath];
return footer;
}
}else{
CollectionHeader_2 *header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeader_2" forIndexPath:indexPath];
return header;
}
}
- 原因分析
在崩溃处,打印方法返回的kind值发现是:UICollectionElementKindSectionFooter ,但是上面代码中进入section==0的分支中并没有给出footer的类,所以报出断言失败。
业务中第一个section不需要footer,所以一开始就没有给出第一个section的footer。但是在返回footer高度时,为section == 0的footer,设置了CGSizeZero。因为有了footer的size所以collectionView会去找一个secction的footer,很遗憾它没有找到,然后就崩了!!!
- 解决方案
修改 返回header 和 footer 方法中的代码逻辑,首先判断kind,确定初始化header还是footer,然后再根据不同的section返回不同的header、footer对象,具体如下:
// 返回header 和 footer
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
if (kind == UICollectionElementKindSectionHeader){
if (indexPath.section == 0){
CollectionHeader_1 *header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeader_1" forIndexPath:indexPath];
return header;
}else{
CollectionHeader_2 *header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeader_2" forIndexPath:indexPath];
return header;
}
}else{
CollectionFooter *footer = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"CollectionFooter" forIndexPath:indexPath];
return footer;
}
}
- 疑问?
目前原来的代码在iOS 12.0的系统上运行平稳,没有出现崩溃,而在iOS 9.x系统中崩溃必现,还不了解为什么?如果有人知道,请告知谢谢。
网友评论