-->

UICollectionView和补充视图(报头)(UICollectionView and Sup

2019-08-17 07:32发布

试图AA补充视图加入到我的UICollectionView作为标题。 我在得到它的工作的问题。

我使用自定义UICollectionViewFlowLayout返回一个contentSize ,始终是至少1个像素较大,则帧(我使用的是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);
}

我创建了一个UICollectionReusableView类这仅仅是一个UIViewUILabel

@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'

如果我注释掉,它运行但没有头。

我在做什么错误或不执行?

Answer 1:

我面临着类似的问题,但我的应用程序崩溃后,我以编程方式弹出我的UICollectionViewController。 在某种原因(我认为这只是在SDK中的错误)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'

该解决方案只是替代-dealloc在UICollectionViewController和手动释放self.collectionView。 ARC的代码:

- (void)dealloc {

    self.collectionView = nil;
}

希望这将节省时间的人。



Answer 2:

本主题中的答案是很老,而且没有在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

希望它会帮助你,你不会浪费我一样多的时间。



Answer 3:

我清理我的代码并删除我在IB创建的UICollectionView和创造这一切的代码。 我又跑了,并得到一个不同的错误,并意识到我没有设置委托或数据源中的IB。 我所做的:

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

但是,绝不能一直不够好。

因此,与UICollectionView在IB,而不是设置在IB的delgate /数据源,而是在代码中创建:

[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"];

是一个问题。 我重做它在所有的代码创建UICollectionView:

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:没有,虽然工作。



Answer 4:

如果你看一下错误信息,上面说的数据源未设置。 这应该可以解决它:

self.collectionView.dataSource = self;

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

YourViewController : UIViewController<UICollectionViewDataSource>



Answer 5:

我也有这个恼人的错误:

*** 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;
}

或SWIFT:

deinit {
    collectionView = nil
}

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

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


Answer 6:

这个答案是相似的,你创建检查数据源的方法的人,但它是一个有点简单。 看来这个问题是关系到集合释放后集合视图的布局坚持围绕。 所以我下面清零布局的属性和错误消失。

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


Answer 7:

我有同样的问题,同样,我是不是正确登记的标题。 这里对于多个线程,所有建议使用笔尖来定义头,但我做不同的,并工作正常。

我有一个自定义标题SizeCollectionHeader,它继承了UICollectionReusableView。 据注册这样的。

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

并且工作正常。

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

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

这将崩溃。

所以,我只是想为正在这里,你不需要用笔尖任何人发表评论。



Answer 8:

试试这个 :

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

它的工作对我来说)



Answer 9:

我一直得到了同样的错误。 我已经建立了我的CollectionView的CustomHeaderView。 我有类集合可重复使用的视图的我CustomHeaderView,我不得不设置标识符。 我半小时试图找出为什么这个是失败。

终止应用程序由于未捕获的异常“NSInternalInconsistencyException”,理由是:“不能出列类型的视图:UICollectionElementKindSectionFooter与标识符SectionHeader - 必须注册标识的笔尖或类或故事板连接原型细胞”

你需要仔细阅读日志...教训。

“不能出列类型的视图:UICollectionElementKindSectionFooter

究其原因是因为在故事板 - 中的CollectionView身份督察检查了两个附件:节头和页脚节。 我只需要一节头。 只要取消躯......建立和run..BOOM!



Answer 10:

一个iOS9错误,在视图控制器的dealloc的集层委托为零。

- (void)dealloc{

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


文章来源: UICollectionView and Supplementary View (header)