带有补充视图/部分 headers 的 UICollectionView 断言失败,数据源为零?

Assertion failure in UICollectionView with supplementary views / section headers, dataSource is nil?

我的应用程序每隔一段时间就会通过 Crashlytics 报告此断言失败:

 Fatal Exception: NSInternalInconsistencyException 
 UICollectionView dataSource is not set

0   CoreFoundation  __exceptionPreprocess + 126
3   Foundation  -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 92
4   UIKit   -[UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:applyAttributes:] + 148
5   UIKit   -[UICollectionView _updateVisibleCellsNow:] + 3398
6   UIKit   -[UICollectionView layoutSubviews] + 240
7   UIKit   -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 514
8   QuartzCore  -[CALayer layoutSublayers] + 136
9   QuartzCore  CA::Layer::layout_if_needed(CA::Transaction*) + 360
10  QuartzCore  CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
11  QuartzCore  CA::Context::commit_transaction(CA::Transaction*) + 222
12  QuartzCore  CA::Transaction::commit() + 324
13  UIKit   _afterCACommitHandler + 132
14  CoreFoundation  __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 20
20  UIKit   UIApplicationMain + 1440
21  NRDB    main.m line 14 main
22  libdyld.dylib   start + 2

在应用程序使用 UICollectionViews 的所有三个地方,我确保 a) 在 XIB 和控制器的 viewDidLoad 方法中都设置了数据源,以及 b) 将其重置为 nil在控制器的 dealloc.

使用

将补充视图(header 视图)添加到 collection 视图
[self.collectionView registerNib:[UINib nibWithNibName:@"HeaderXib" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"sectionHeader"];

对于 header 的观看次数,我使用的是 CSStickyHeaderFlowLayout

到目前为止,我无法在本地重现此内容。关于可能是什么问题,甚至如何找出涉及三个视图中的哪一个,有什么想法吗?

尽量减少猜测:

Subclass 您的 collection 视图,无论您在哪里使用它们,范围限于该位置:

@interface MyDetailViewController_CollectionView : UICollectionView

@end

@implentation MyDetailViewController_CollectionView

-(void)layoutSubviews{
    //When the stacktrace is generated, it will now include -[MyDetailViewController_CollectionView layoutSubviews]
    [super layoutSubviews];
}

@end

然后将这些控制器设置为具有相应 collection 视图的实例。这可以通过设置自定义 class.

在界面生成器中完成

如果你实现了这个,手动触发异常以确保堆栈跟踪看起来像你想要的那样。您应该可以在 -collectionView:cellForItemAtIndexPath:

中完成

UICollectionView.dataSource弱

看起来可能的情况是控制器正在被破坏,但 collection 视图以某种方式幸存下来。

当您释放控制器时,确保对 collection 视图和任何包含视图的所有强引用都设置为 nil。

UIView 可以在视图层级中存活

在 dealloc 上添加一个断言 NSAssert(self.collectionView.window == nil)。如果 window 不为 nil,则 collection 视图是视图层次结构的一部分,即使控制器已被销毁,也可以接收布局事件。

这可能是由于

  • 手动adding/removing视图控制器视图到视图层次结构

  • 在关闭动画完成之前取消分配视图控制器