UICollectionView和Supplementary View(标题)

Pad*_*215 17 objective-c ios uicollectionview uicollectionviewlayout

试图在我UICollectionView的标题中添加一个补充视图.我有问题让它工作.

我使用一个自定义UICollectionViewFlowLayout来返回一个contentSize总是至少比帧大1个像素(我使用的UIFreshControl只有UICollectionView滚动,并且设置collectionView.contentSize直接无效)并invalidateLayout打开sectionInsertitemSize更改:

-(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);
}
Run Code Online (Sandbox Code Playgroud)

我创建了一个UICollectionReusableView类,它只是UIView一个UILabel:

@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;
}
Run Code Online (Sandbox Code Playgroud)

试图实现它:

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;
Run Code Online (Sandbox Code Playgroud)

我注册了课程:

[self.collectionView registerClass:[CollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"];
Run Code Online (Sandbox Code Playgroud)

并实现委托:

-(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;
}
Run Code Online (Sandbox Code Playgroud)

这条线

collectionViewFlowLayout.headerReferenceSize = CGSizeMake(0, 100);
Run Code Online (Sandbox Code Playgroud)

导致错误:

*** 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'
Run Code Online (Sandbox Code Playgroud)

如果我发表评论,它会运行,但没有标题.

我做错了什么或者没有实施?

m8l*_*abs 13

我遇到了类似的问题,但在我以编程方式弹出我的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'
Run Code Online (Sandbox Code Playgroud)

解决方案是在UICollectionViewController中覆盖-dealloc并手动释放self.collectionView.ARC代码:

- (void)dealloc {

    self.collectionView = nil;
}
Run Code Online (Sandbox Code Playgroud)

希望这会为某人节省时间.


Mic*_*ael 10

本主题中的答案很老,在iOS8和iOS9中不起作用.如果您仍然遇到所述问题,请查看以下主题:UICollectionView和Supplementary View崩溃

编辑:

如果链接无效,这是答案:

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

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
Run Code Online (Sandbox Code Playgroud)

结果应如下所示:

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

此更改解决了以下问题:

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

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

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

希望它会对你有所帮助,你不会浪费我那么多的时间.


Pad*_*215 7

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

self.collectionView.delegate = self;
self.collectionView.datasource = self;
Run Code Online (Sandbox Code Playgroud)

但那肯定不够好.

因此,在IB中创建的UICollectionView并没有在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"];
Run Code Online (Sandbox Code Playgroud)

是一个问题.我重新编写它以在代码中创建所有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;
Run Code Online (Sandbox Code Playgroud)

我得到一个不同的错误:

*** 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'
Run Code Online (Sandbox Code Playgroud)

我会试着弄明白.

编辑:

想通了,我正在错误地注册标题:

[collectionView registerClass:[CollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"];
Run Code Online (Sandbox Code Playgroud)

切换到:

UINib *headerNib = [UINib nibWithNibName:@"CollectionHeaderView" bundle:nil];

[collectionView registerNib:headerNib forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderView"];
Run Code Online (Sandbox Code Playgroud)

一切正常.不完全确定它registerClass:是如何工作的.


Fra*_*ano 1

如果你看一下错误信息,它说的是数据源没有设置。这应该可以修复它:

self.collectionView.dataSource = self;

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

YourViewController : UIViewController<UICollectionViewDataSource>