前言
用Xcode 16 打包我们原来的老项目后,进入详情页面直接闪退,分析后发现是CollectionView header部分的 dequeueReusableSupplementaryView导致的
代码分析
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if headerView == nil {
// Initialize the header view only once
headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "PCEqumentControlCollectionReusableView", for: indexPath) as? PCEqumentControlCollectionReusableView
headerView?.delegate = self
}
//这里理解为数据处理
headerView?.reloadData()
return headerView!
}
闪退信息
Trapped uncaught exception 'NSInternalInconsistencyException', reason: 'The collection view's
data source returned a supplementary view that is in the reuse queue. Supplementary views
must be retrieved by calling
dequeueConfiguredReusableSupplementaryViewWithRegistration:forIndexPath: or -
dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:. Collection view:
<UICollectionView: 0x114978000; frame = (0 91; 390 719); clipsToBounds = YES; autoresize =
RM+BM; gestureRecognizers = <NSArray: 0x302d0aaf0>; backgroundColor =
UIExtendedSRGBColorSpace 0.0588235 0.0862745 0.117647 1; layer = <CALayer:
0x302316f60>; contentOffset: {0, 0}; contentSize: {390, 773}; adjustedContentInset: {0, 0, 0, 0};
layout: <UICollectionViewFlowLayout: 0x105f06580>; dataSource:
<ios_eynamics_app.PCEquipmentControlViewController: 0x105e8b200>>; element kind:
UICollectionElementKindSectionHeader; index path: (0-0); supplementary view:
<ios_eynamics_app.PCEqumentControlCollectionReusableView: 0x1149a6680; baseClass =
UICollectionReusableView; frame = (0 0; 390 443); clipsToBounds = YES; hidden = YES; opaque
= NO; layer = <CALayer: 0x30230a840>>'
(
经过分析后
collectionView.dequeueReusableSupplementaryView为这里导致的闪退
后续代码修改
// if headerView == nil {
// Initialize the header view only once
headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "PCEqumentControlCollectionReusableView", for: indexPath) as? PCEqumentControlCollectionReusableView
headerView?.delegate = self
// }
注释掉headerView == nil 就可以了 每次都让他dequeueReusableSupplementaryView
结论分析
dequeueReusableSupplementaryView 和 cellForItem 一样,强制 dequeue 了,Xcode 16的编译环境 新加了一个断言, 没有执行dequeueReusableSupplementaryView 就给他赋值或者处理就会闪退。
例如
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PCEquipmentControlCollectionViewCell", for: indexPath) as! PCEquipmentControlCollectionViewCell
return cell
}
这个就是每次都dequeue的,后面注意SupplementaryView也要这样了。