带有补充视图/节标题的 UICollectionView 中的断言失败,dataSource 为 nil?
Posted
技术标签:
【中文标题】带有补充视图/节标题的 UICollectionView 中的断言失败,dataSource 为 nil?【英文标题】:Assertion failure in UICollectionView with supplementary views / section headers, dataSource is nil? 【发布时间】:2015-03-29 10:56:49 【问题描述】:我的应用程序每隔一段时间就会通过 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 987654324@.
使用
将补充视图(标题视图)添加到集合视图中[self.collectionView registerNib:[UINib nibWithNibName:@"HeaderXib" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"sectionHeader"];
对于标题视图,我使用的是CSStickyHeaderFlowLayout。
到目前为止,我无法在本地重现此内容。关于可能是什么问题的任何想法,或者甚至如何弄清楚这三个视图中的哪一个?
【问题讨论】:
“我无法在本地重现此内容。”你能告诉我们你一直在做什么来测试它吗?您是否可以访问应用崩溃的相同类型的设备? 这基本上意味着我从未在模拟器或任何我的两台 iPad(Air 和 mini,这是一个仅限 iPad 的应用程序)中的任何一台上看到崩溃。此外,到目前为止,我的任何 Testflight 测试人员都没有发生这种情况。 re:我一直在做的测试:因为我不知道涉及 UICollectionView 的三种用途中的哪一种,所以我只是在所有三个地方都尝试了各种“不寻常”的行为,无济于事。我很确定这在“正常”使用期间不会发生,与 Crashlytics 中的 58 份报告相比,该应用程序有几千名用户,所以我猜这一定是一些罕见的 egde 案例,我的首要任务是找出哪个视图是罪魁祸首。 没有办法让 Crashlytics 在加载之前告诉您它正在尝试加载哪个视图?错误发生在哪个版本的 ios 上没有一致性? (很遗憾,无法联系收到错误的人。) 我不知道。该应用程序的下一个版本将在崩溃后启动时发出“oops”警报,要求人们告诉我他们刚刚做了什么。 【参考方案1】:尽量减少猜测:
将您的集合视图子类化到您使用它们的任何位置,范围为该位置:
@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
然后将这些控制器设置为具有其相应集合视图的实例。这可以通过设置自定义类在界面生成器中完成。
如果您实现此功能,请手动触发异常以确保堆栈跟踪看起来符合您的要求。你应该可以在 -collectionView:cellForItemAtIndexPath:
UICollectionView.dataSource 很弱
看起来可能的情况是控制器正在被销毁,但集合视图以某种方式幸存下来。
当您释放控制器时,请确保对集合视图和任何包含视图的所有强引用都设置为 nil。
UIView 可以在视图层次结构中生存
在 dealloc 上添加一个断言 NSAssert(self.collectionView.window == nil)。如果窗口不为 nil,则集合视图是视图层次结构的一部分,即使控制器已被销毁,也可以接收布局事件。
这可能是由于
在视图层次结构中手动添加/删除视图控制器视图
在其解除动画完成之前释放视图控制器
【讨论】:
感谢子类化建议,我将立即添加。 Re: dataSource 很弱,我知道这一点,我的 deallocself.collectionView.delegate = nil; self.collectionView.dataSource = nil; self.collectionView = nil;
我的视图控制器被解除分配但视图仍在层次结构中,这是由于动画或其他一些超出简单导航控制器的机制。
您如何检测/避免此类情况? self.collectionView=nil
在viewWillDisappear
中可能吗?
在 dealloc 上添加一个断言NSAssert(self.collectionView.window == nil)
。如果窗口不为零,则集合视图可以在控制器被销毁后接收布局事件。我不建议将 [self.collectionView removeFromSuperview]
添加到 dealloc,因为您不必这样做。问题可能在于类之外的自定义转换或类似的东西。以上是关于带有补充视图/节标题的 UICollectionView 中的断言失败,dataSource 为 nil?的主要内容,如果未能解决你的问题,请参考以下文章
带有部分标题的 UICollectionViewWaterfallLayout?
如何在 Objective-C 中将带有补充视图的标题添加到 UiCollectionView?