UICollectionView和补充视图(标题)

试图添加一个补充视图到我的UICollectionView作为标题。 我有问题得到它的工作。

我使用自定义的UICollectionViewFlowLayout来返回一个contentSize总是至less1像素大于框架(我正在使用UIFreshControl这将只工作,如果UICollectionView滚动,并设置collectionView.contentSize直接什么都不做),并invalidateLayoutsectionInsertitemSize更改:

 -(void)setSectionInset:(UIEdgeInsets)sectionInset { if (UIEdgeInsetsEqualToEdgeInsets(super.sectionInset, sectionInset)) { return; } super.sectionInset = sectionInset; [self invalidateLayout]; } -(void) setItemSize:(CGSize)itemSize { if (CGSizeEqualToSize(super.itemSize, itemSize)) { return; } super.itemSize = itemSize; [self invalidateLayout]; } - (CGSize)collectionViewContentSize { CGFloat height = [super collectionViewContentSize].height; // Always returns a contentSize larger then frame so it can scroll and UIRefreshControl will work if (height < self.collectionView.bounds.size.height) { height = self.collectionView.bounds.size.height + 1; } return CGSizeMake([super collectionViewContentSize].width, height); } 

我创build了一个UICollectionReusableView类,它只是一个带有UILabelUIView

 @implementation CollectionHeaderView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"CollectionHeaderView" owner:self options:nil]; if ([arrayOfViews count] < 1) { return nil; } if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) { return nil; } self = [arrayOfViews objectAtIndex:0]; self.headerLabel.text = @"This is a header. There are many like it."; self.backgroundColor = [UIColor yellowColor]; } return self; } 

试图实现它:

 DatasetLayout *collectionViewFlowLayout = [[DatasetLayout alloc] init]; collectionViewFlowLayout.itemSize = CGSizeMake(360, 160); collectionViewFlowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; collectionViewFlowLayout.sectionInset = UIEdgeInsetsMake(16, 16, 16, 16); collectionViewFlowLayout.minimumInteritemSpacing = 16; collectionViewFlowLayout.minimumLineSpacing = 16; collectionViewFlowLayout.headerReferenceSize = CGSizeMake(0, 100); UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:collectionViewFlowLayout]; collectionView.translatesAutoresizingMaskIntoConstraints = FALSE; collectionView.backgroundColor = [UIColor yellowColor]; collectionView.delegate = self; collectionView.dataSource = self; 

我注册了课程:

 [self.collectionView registerClass:[CollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"]; 

并执行委托:

 -(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { CollectionHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView" forIndexPath:indexPath]; headerView.headerLabel.text = @"Blarg!"; return headerView; } 

该线

 collectionViewFlowLayout.headerReferenceSize = CGSizeMake(0, 100); 

导致错误:

 *** Assertion failure in -[UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:], /SourceCache/UIKit_Sim/UIKit-2380.17/UICollectionView.m:1150 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView dataSource is not set' 

如果我注释掉它,它会运行,但没有标题。

我做错了什么或不执行?

我面临类似的问题,但我的程序崩溃后,我编程popup我的UICollectionViewController。 由于某种原因(我认为这只是SDK中的一个bug),self.collectionView在其控制器销毁后仍然活着,从而导致这种失败:

 *** Assertion failure in -[UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:applyAttributes:], /SourceCache/UIKit/UIKit-2935.137/UICollectionView.m:1305 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView dataSource is not set' 

解决方法是在UICollectionViewController中重写-dealloc并手动释放self.collectionView。 ARC代码:

 - (void)dealloc { self.collectionView = nil; } 

希望这会为别人节省时间。

在这个主题的答案是相当古老的,不适用于iOS8和iOS9。 如果您仍然遇到上述问题,请查看以下主题: UICollectionView和补充视图崩溃

编辑

这是答案,万一链接失效:

如果您在集合视图中使用自定义布局,请检查其数据源是否在:

 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 

结果应该是这样的:

 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect if (self.collectionView.dataSource != nil) { // Your layout code return array; } return nil; } 

此更改解决了以下问题:

  • 断言失败 – [UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:applyAttributes:]

您也可以检查以下主题,但是在我的情况下它没有解决任何问题:

如果部分标题隐藏在UICollectionView中,则删除空白空间

希望它能帮助你,而且不会像我那样浪费时间。

我清理了我的代码,并删除了我在IB中创build的UICollectionView,并在代码中创build了它。 我再次运行它,得到了一个不同的错误,并意识到我没有在IB中设置委托或数据源。 我做了:

 self.collectionView.delegate = self; self.collectionView.datasource = self; 

但这一定不够好。

所以在IB中创buildUICollectionView,而不是在IB中设置delgate / datasource,而是在代码中:

 [self.view bringSubviewToFront:self.collectionView]; self.collectionView.collectionViewLayout = collectionViewFlowLayout; self.collectionView.backgroundColor = [UIColor orangeColor]; self.collectionView.delegate = self; self.collectionView.dataSource = self; [self.collectionView registerClass:[DatasetCell class] forCellWithReuseIdentifier:@"cvCell"]; [self.collectionView registerClass:[CollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"]; 

是一个问题。 我redid它创buildUICollectionView全部在代码中:

 UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:collectionViewFlowLayout]; collectionView.translatesAutoresizingMaskIntoConstraints = FALSE; collectionView.backgroundColor = [UIColor yellowColor]; collectionView.delegate = self; collectionView.dataSource = self; [collectionView registerClass:[DatasetCell class] forCellWithReuseIdentifier:@"cvCell"]; [collectionView registerClass:[CollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"]; [self.view addSubview:collectionView]; self.collectionView = collectionView; 

我得到一个不同的错误:

 *** Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2380.17/UICollectionView.m:2249 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindSectionHeader with identifier CollectionHeaderView - must register a nib or a class for the identifier or connect a prototype cell in a storyboard' 

我会试图找出。

编辑:

想通了,我正在注册头不正确:

 [collectionView registerClass:[CollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"]; 

切换到:

 UINib *headerNib = [UINib nibWithNibName:@"CollectionHeaderView" bundle:nil]; [collectionView registerNib:headerNib forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"]; 

一切正常。 不完全确定registerClass:虽然不工作。

如果您查看错误消息,则表示数据源未设置。 这应该解决它:

self.collectionView.dataSource = self;

确保你的视图控制器实现数据源协议:

YourViewController : UIViewController<UICollectionViewDataSource>

这个答案与其他创build一个检查数据源的方法类似,但是它更简单一些。 这个问题似乎与集合发布后收集视图的布局有关。 所以我清除布局的属性如下所示,错误消失。

 deinit { let layout = self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout layout.estimatedItemSize = CGSizeZero layout.sectionInset = UIEdgeInsetsZero layout.headerReferenceSize = CGSizeZero } 

我也有这个恼人的错误:

 *** Assertion failure in -[UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:applyAttributes:], /SourceCache/UIKit/UIKit-3347.44/UICollectionView.m:1400 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView dataSource is not set' 

我发现一些人通过这样做来解决这个错误

 - (void)dealloc { self.collectionView = nil; } 

或迅速:

 deinit { collectionView = nil } 

然而这些解决了我的崩溃。 我尝试了一些东西,下面的“黑客”解决了这个烦人的错误:

 func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { if collectionView.dataSource != nil { return someHeaderSize } else { return CGSizeZero } } 

我有同样的问题,同样,我没有正确注册头。 在这里有几个线程,都build议使用一个笔尖来定义标题,但我已经做了不同的工作正常。

我有一个自定义标题SizeCollectionHeader,它inheritance了UICollectionReusableView。 它是这样登记的。

  [self.collectionView registerClass:[GRSizeCollectionHeader class] forSupplementaryViewOfKind:@"UICollectionElementKindSectionHeader" withReuseIdentifier:@"SupplementaryViewIdentifier"]; 

并且工作正常。

我最初的问题是,有这样一个随机的“种”值。

  [self.collectionView registerClass:[GRSizeCollectionHeader class] forSupplementaryViewOfKind:@"SupplementaryViewKind" withReuseIdentifier:@"SupplementaryViewIdentifier"]; 

这将会崩溃。

所以我只想评论任何人在这里看到你不需要使用笔尖。

尝试这个 :

 self.collectionView?.dataSource = nil self.collectionView = nil 

它为我工作;)

我一直得到同样的错误。 我为我的collectionView设置了CustomHeaderView。 我有我的CustomHeaderView集合可重用视图的类,我已经设置了标识符。 我花了1/2小时试图弄清楚为什么这是失败的。

由于未捕获的exception“NSInternalInconsistencyException”而终止应用程序,原因:'无法使types视图脱离:带有标识符的UICollectionElementKindSectionFooter SectionHeader – 必须为标识符注册一个nib或一个类,或者在故事板中连接一个原型单元格'

你需要仔细阅读日志…吸取了教训。

“无法出列类似的观点:UICollectionElementKindSectionFooter

原因是因为在故事板中 – 在collectionView Identity Inspector中,我已经检查了两个附件:Section Header和Section Footer。 我只需要部分标题。 只需取消选中页脚…构build并运行.BOOM!

一个iOS9的bug,在viewcontroller的dealloc set layer delegate nil中。

 - (void)dealloc{ if ([[[UIDevice currentDevice] systemVersion] hasPrefix:@"9"]) { self.collectionView.layer.delegate = nil; } }