UICollectionView中的断言失败 _createPreparedCellForItem。

3

编辑:对于任何遇到这个问题的人,我已经找到了一个解决方案,并在下面进行了回答。

原始问题

我正在尝试构建一个具有两种类型单元格的双列、多节 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

在阅读了有关类似主题的一些/其他/问题之后,我有一些理论。

我以前认为这与我使用两种不同大小有关,但这是不正确的,因为我像上面展示的那样手动覆盖了所需的方法,并且我从未设置UICollectionViewFlowLayout对象的itemSize属性。

我有另一个理论,可能是在使用UICollectionView注册我的Nibs/Classes时出了些问题。由于我有两个类可用于项目填充,根据我从UICollectionView.h的注释中收集到的信息,特别是第102-104行,应该只有一个与视图相关联的已注册类/nib。因此,我注释掉了nibs的注册,并且在cellForItemAtIndexPath中不再调用dequeueReusableCellWithReuseIdentifier:,而是将一个新单元格初始化为nil,然后让我的逻辑从其适当的nib中创建新单元格,而不是允许CollectionView尝试使用自己的内部逻辑进行出列或生成新单元格(我知道Apple最近实施了这项措施,将UICollectionViewUITableView在这方面区分开来)。不幸的是,我仍然遇到了这个断言失败。

我已经没有更多的想法了,如果有人可以帮助我解决这个问题,我会很高兴。如果还有任何我可能错过的信息,请告诉我,我会很乐意提供它。

1个回答

2

原问题的解决方案

我找出了问题所在。

基本上,我的理论是正确的,问题源于将 Nibs 注册为可由 CollectionView 取消排队。但我之前做的是注册两个不同的 UICollectionView 子类以供重复使用,这没问题,但我使用了相同的恢复标识符,因此 CollectionView 不知道应该取消哪个。我修改了代码,将它们注册如下:

[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知道要使用哪个单元格。我上面展示的调整大小方法也是正确的,如果你计划使用多个单元格,那么正确使用该方法非常重要,以使所有内容协调工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接