UICollectionView _createPreparedCellForItem 中的断言失败

Posted

技术标签:

【中文标题】UICollectionView _createPreparedCellForItem 中的断言失败【英文标题】:Assertion failure in UICollectionView _createPreparedCellForItem 【发布时间】:2014-05-07 19:28:57 【问题描述】:

编辑对于遇到此问题的任何人,我已经用适合我的解决方案回答了我的问题,您可以在下面找到。

原始问题

我正在尝试使用两种类型的单元格构建一个两列、多节的 UICollectionView。我的目标有两种基本状态(每个部分):

至少要显示一项 至少显示一个代表项目的单元格,其中每个单元格的宽度是整个 CollectionView 的一半 没有要显示的项目 显示一个表示空状态的特殊单元格,其宽度是正常单元格的两倍(因此它占据了该“行”的 CollectionView 的整个宽度)

我已经为此构建了我认为正确的设置,包括覆盖下面的 CollectionViewDelegateFlowLayout 方法:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

    return [self trueSectionCount:indexPath.section] > 0 ? CGSizeMake(kItemCellWidth, kItemCellHeight) : CGSizeMake(kItemCellEmptyWidth, kItemCellEmptyHeight);

它返回一个合适的尺寸,匹配一些与两种状态的单元格相同的尺寸。


我的问题如下:cellForItemAtIndexPath:方法中创建第一个单元格,随后返回后,抛出断言失败,如下:

*** Assertion failure in -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:], /SourceCache/UIKit_Sim/UIKit-2935.137/UICollectionView.m:1289

在阅读了some / other / questions 类似的主题后,我有了一些理论。

我之前认为这与我使用两种不同尺寸的事实有关,但这是不对的,因为我手动覆盖了上面显示的所需方法,而且我从未设置我的UICollectionViewFlowLayout 对象的itemSize 属性。

我的另一个理论是,这可能是由在UICollectionView 注册我的 Nibs/Classes 时发生的一些有趣的事情引起的。由于我有两个可以在任何给定时间用于项目填充的类,并且根据我从UICollectionView.h 中的 cmets 收集的内容,特别是 102-104 行,应该只有一个注册的类/笔尖与视图相关联。所以我注释掉了笔尖的注册,而不是在cellForItemAtIndexPath中调用dequeueReusableCellWithReuseIdentifier:,我只是将一个新单元初始化为nil,然后允许我的逻辑从其适当的笔尖创建新单元,而不是允许@ 987654335@ 尝试使用它自己的内部逻辑(我知道 Apple 最近实施了它,在这方面将 UICollectionViewUITableView 区分开来)尝试和出列或生成一个新单元格。不幸的是,我仍然遇到这个断言失败。

我的想法已经用完了,我很想知道是否有人可以帮助我解决这个问题。如果有任何我可能遗漏的信息,请告诉我,我很乐意提供。

【问题讨论】:

【参考方案1】:

原始问题的解决方案

我已经找到问题所在了。

基本上我的理论是正确的,即问题源于将 Nib 注册为由CollectionView 出列。我 正在 做的是注册两个不同的 UICollectionView 子类以重新使用,这很好,除了我对两者都使用 same 恢复标识符,所以 @ 987654323@ 不知道要出列哪一个。我更改了我的代码以这样注册它们:

[self.collectionView registerNib:[UINib nibWithNibName:@"SomeItemCell" bundle:nil] forCellWithReuseIdentifier:CellIdentifier];
[self.collectionView registerNib:[UINib nibWithNibName:@"SomeEmptyItemCell" bundle:nil] forCellWithReuseIdentifier:EmptyCellIdentifier];

然后随后使用它们自己的标识符适当地使单元格出队:

if (there are items to show in this section)

    SomeItemCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
    ... code ...
    return cell;

else

    SomeEmptyItemCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:EmptyCellIdentifier forIndexPath:indexPath];
    ... code ...
    return cell;

这确保了CollectionView 确切地知道要使用哪个单元格。我上面展示的大小调整方法也是正确的,如果您打算使用多个单元格,那么该方法非常重要,以便正确地使所有内容很好地协同工作。

【讨论】:

以上是关于UICollectionView _createPreparedCellForItem 中的断言失败的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 断言失败 -[UICollectionView _updateWithItems:tentativelyForReordering:]

UICollectionView 性能 - _updateVisibleCellsNow

UICollectionView 上的 register(_:forCellWithReuseIdentifier:) 有啥问题?

UICollectionView _createPreparedCellForItem 中的断言失败

-[UICollectionView _endItemAnimations] 崩溃中的断言失败

ios 7 中的 -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] 断言