UICollectionView和补充视图(标题)
试图添加一个补充视图到我的UICollectionView
作为标题。 我有问题得到它的工作。
我使用自定义的UICollectionViewFlowLayout
来返回一个contentSize
总是至less1像素大于框架(我正在使用UIFreshControl
这将只工作,如果UICollectionView
滚动,并设置collectionView.contentSize
直接什么都不做),并invalidateLayout
上sectionInsert
和itemSize
更改:
-(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
类,它只是一个带有UILabel
的UIView
:
@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; } }