CollectionView iOS意外崩溃



我发现了一个来自用户的崩溃分析,但在我的终端是不可复制的。

项目在多个地方使用集合视图,我甚至已经验证了单元格类在故事板中被正确设置。

注意:代码使用RxSwift.

任何帮助都将是非常感激的。

Fatal Exception: NSInternalInconsistencyException
the cell returned from -collectionView:cellForItemAtIndexPath: does not have a reuseIdentifier - cells must be retrieved by calling -dequeueReusableCellWithReuseIdentifier:forIndexPath:

Fatal Exception: NSInternalInconsistencyException
0  CoreFoundation                 0x1ae60b298 __exceptionPreprocess
1  libobjc.A.dylib                0x1c2365480 objc_exception_throw
2  CoreFoundation                 0x1ae518cc8 -[CFPrefsSearchListSource addManagedSourceForIdentifier:user:]
3  Foundation                     0x1af850128 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
4  UIKitCore                      0x1b062c7c0 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:]
5  UIKitCore                      0x1b062dce8 -[UICollectionView _prefetchItemsForPrefetchingContext:maxItemsToPrefetch:]
6  UIKitCore                      0x1b0635634 -[UICollectionView layoutSubviews]
7  UIKitCore                      0x1b13ae6d4 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
8  QuartzCore                     0x1b1824424 -[CALayer layoutSublayers]
9  QuartzCore                     0x1b182abac CA::Layer::layout_if_needed(CA::Transaction*)
10 QuartzCore                     0x1b183616c CA::Layer::layout_and_display_if_needed(CA::Transaction*)
11 QuartzCore                     0x1b177e578 CA::Context::commit_transaction(CA::Transaction*, double, double*)
12 QuartzCore                     0x1b17a92c8 CA::Transaction::commit()
13 QuartzCore                     0x1b17aa530 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*)
14 CoreFoundation                 0x1ae589588 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
15 CoreFoundation                 0x1ae583bb8 __CFRunLoopDoObservers
16 CoreFoundation                 0x1ae584154 __CFRunLoopRun
17 CoreFoundation                 0x1ae583818 CFRunLoopRunSpecific
18 GraphicsServices               0x1c4c89570 GSEventRunModal
19 UIKitCore                      0x1b0eaf0e8 -[UIApplication _run]
20 UIKitCore                      0x1b0eb4664 UIApplicationMain

cellForItemAt

代码
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.identifier, for: indexPath) as? MyCollectionViewCell else{return UICollectionViewCell()}
cell.config(collectionView.tag == 1 ? dataSourceFirst[indexPath.row] : dataSourceSecond[indexPath.row])
return cell
}

对于面临同样问题的人:return UICollectionViewCell()正在导致崩溃。

不要把UICollectionViewCell和UITableViewCell混在一起,初始化后返回是安全的。

修复方法非常简单:

  1. 在集合视图设置过程中为重用标识符注册单元格类型collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
  2. 而不是init (return UICollectionViewCell())只是为相同的标识符脱队列相同的细胞类型。collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)

在我的例子中是这样的:

func setupCollectionView() {
...
collectionView.registerCell(EmptyCell.self)
...
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let controller = controller else {
//instead of return UICollectionViewCell()
return collectionView.dequeueCell(EmptyCell.self, indexPath: indexPath).setup(.songDetails)
}
let cell = collectionView.dequeueCell(SectionSongMenuCell.self, indexPath: indexPath)
...
return cell
}
***
extension UICollectionView {
func registerCell<T: UICollectionViewCell>( _ type: T.Type) {
self.register(type.nib, forCellWithReuseIdentifier: type.identifier)
}
func dequeueCell<T: UICollectionViewCell>(_ type: T.Type, indexPath: IndexPath) -> T {
return self.dequeueReusableCell(
withReuseIdentifier: type.identifier,
for: indexPath) as! T
}
}

最新更新